diff --git a/.gitattributes b/.gitattributes index 0ecaca90..0839efd8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,11 @@ -/demo export-ignore -/tests export-ignore -.gitattributes export-ignore -.gitignore export-ignore -.travis.yml export-ignore -composer.lock export-ignore -phpunit.xml export-ignore +/demo export-ignore +/tests export-ignore +/scripts export-ignore +/.github export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.php_cs.dist export-ignore +.travis.yml export-ignore +phpunit.xml.dist export-ignore +/tests/cache/4pda.to.2022-12-04-406834-sostoyalsya_reliz_clown_of_duty_parodii_na_call_of_duty.php working-tree-encoding=windows-1251 diff=windows-1251 +/tests/cache/www.itmedia.co.jp.news-articles-2410-28-news159.html.php working-tree-encoding=sjis diff=sjis diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..13871fc1 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +github: oscarotero +patreon: misteroom +custom: "https://paypal.me/oscarotero" \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..9e6af5d3 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,70 @@ +name: "testing" + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + + strategy: + matrix: + php: + - 7.4 + - 8.0 + - 8.1 + - 8.2 + - 8.3 + - 8.4 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + + - name: Cache PHP dependencies + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-php-${{ matrix.php }}-composer- + + - name: Install dependencies + run: composer install + + - name: Tests + run: composer test + + phpstan: + name: PHPStan Static Analysis + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + + - name: Cache PHP dependencies + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-php-8.4-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-php-8.4-composer- + + - name: Install dependencies + run: composer install + + - name: Run PHPStan + run: composer phpstan diff --git a/.gitignore b/.gitignore index f317d741..29e4a489 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -# COMPOSER -vendor +*.cache +*.code-workspace composer.lock +env.php +phpunit.xml +vendor diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 00000000..31a8de65 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,13 @@ +setFinder( + PhpCsFixer\Finder::create() + ->files() + ->name('*.php') + ->in(__DIR__.'/src') + ->in(__DIR__.'/demo') + ->in(__DIR__.'/tests') + ->exclude('cache') + ->exclude('fixtures') + ); \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1ecfee99..00000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: php -sudo: false - -php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm - -matrix: - allow_failures: - - php: hhvm - -before_install: - - composer install - -script: - - 'phpunit' - - './vendor/bin/php7cc ./src' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..5f4b497f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,302 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [4.4.17] - 2025-05-13 +### Fixed +- Adapters hostname detection [#556]. + +## [4.4.16] - 2025-05-09 +### Fixed +- Adapters hostname detection [#555]. + +## [4.4.15] - 2025-01-02 +### Fixed +- Type bug [#553]. + +## [4.4.14] - 2024-12-04 +### Fixed +- Php 8.4 support [#551]. + +## [4.4.13] - 2024-11-21 +### Fixed +- Php 8.4 support [#548]. + +## [4.4.12] - 2024-07-24 +### Fixed +- X.com (Twitter) [#540] +- Updated oembed resources. + +## [4.4.11] - 2024-06-10 +### Fixed +- Updated oEmbed entry points [#537] + +## [4.4.10] - 2023-12-10 +### Fixed +- PHP 7.4 support +- Use correct method for string length [#529] + +## [4.4.9] - 2023-12-01 +### Fixed +- Performance and memory leak issues [#525], [#527]. + +## [4.4.8] - 2023-05-22 +### Fixed +- Support for `psr/http-message@2` [#514], [#515] + +## [4.4.7] - 2022-12-12 +### Fixed +- Href attributes with `undefined` values [#501], [#502] +- Deprecated warning for var interpolation in PHP 8.2 [#506] +- Prevent unsupported operand types exception [#507] + +## [4.4.6] - 2022-10-02 +### Fixed +- Some code issues detected by phpstan: [#495], [#496], [#497], [#498]. +- Fix for quotation marks in redirect URL [#499] + +## [4.4.5] - 2022-09-06 +### Fixed +- Updated oembed endpoints [#494] + +## [4.4.4] - 2022-04-13 +### Fixed +- Error getting data from Linked data [#481]. + +## [4.4.3] - 2022-03-13 +### Fixed +- PHP 8.1 deprecation notice [#480]. + +## [4.4.2] - 2022-02-13 +### Added +- Options to customize the CurlClient to perform http queries [#474]. + +## [4.4.1] - 2022-02-06 +### Fixed +- PHP 8.1 deprecation notice [#473]. + +## [4.4.0] - 2022-01-08 +### Added +- New settings option `twitter:token` to use Twitter API to get the data [#364] [#468]. + +### Fixed +- Headers not sent properly by curl [#466], [#467]. + +## [4.3.5] - 2021-10-10 +### Fixed +- Updated oEmbed endpoints +- Fixed embed code for Instagram [#456], [#459] + +### Security +- Fixed a possible XML Quadratic Blowup vulnerability. + +## [4.3.4] - 2021-06-22 +### Fixed +- Urls of images should include the same url for the `$info->image` value. [#452] + +## [4.3.3] - 2021-06-22 +### Fixed +- Facebook embed redirects to `/login`. [#450], [#451] + +## [4.3.2] - 2021-04-04 +### Fixed +- Add configured oEmbed query parameters to all oEmbed endpoints [#437] +- Updated oEmbed endpoints. +- Replaced Travis with Github workflows for testing + +## [4.3.1] - 2021-03-21 +### Added +- Support for binary files (video, audio, images, etc) [#412] [#413] + +### Fixed +- Oembed for facebook photos [#405] [#406] +- Oembed for facebook videos [#432] [#433] +- Added more ways to detect data using meta tags [#427] +- Bandcamp provider name [#429] [#430] + +## [4.3.0] - 2020-11-04 +### Added +- New function `$embed->setSettings()` to pass the settings before get the site info + +### Fixed +- PHP 8 compatibility [#394] +- Facebook and Instagram adapted to the new API changes [#392] [#399] + +## [4.2.7] - 2020-09-23 +### Added +- New option `twitch:parent` to fix Twitch embed with iframes [#384] + +### Fixed +- Added `datePublished` check to `PublishedTime` extractor [#385] [#386] +- Added `@property-read` for IDE suppport [#387] [#388] + +## [4.2.6] - 2020-08-28 +### Fixed +- Code width and height when the provided value is not numeric (ex: 100%) [#380] + +## [4.2.5] - 2020-08-01 +### Fixed +- Github TypeError exception with some urls [#375] + +## [4.2.4] - 2020-07-06 +### Fixed +- Ignore invalid urls instead throw an exception +- Updated oembed list of endpoints + +## [4.2.3] - 2020-06-12 +### Fixed +- Suppport for other non-latin alphabets such Persian or Arabic [#366] + +## [4.2.2] - 2020-05-31 +### Fixed +- Provided a fallback for oEmbed compatible sites like Instagram that redirects to login page [#357] + +## [4.2.1] - 2020-05-25 +### Fixed +- Redirect urls like `t.co`. + +## [4.2.0] - 2020-05-23 +### Added +- Added the `ignored_errors` settings to ignore some curls errors instead throw an exception [#355] +- Support for Twitch embeds [#332] + +### Fixed +- Ignored linkedData errors [#356] + +## [4.1.1] - 2020-04-24 +### Added +- Updated oembed endpoints from `oembed.com` +- Add support for tiktok.com + +## [4.1.0] - 2020-04-19 +### Added +- Ability to send settings to `CurlClient`. Added the `cookies_path` setting to customize the file used for cookies. [#345] +- `Document::selectCss()` function to select elements using css selectors instead xpath (it requires `symfony/css-selector`) +- `Document::removeCss()` function to remove elements using css selectors instead xpath (it requires `symfony/css-selector`) +- Ability to configure OEmbed parameters from the outside using the `oembed:query_parameters` setting [#346] + +## [4.0.0] - 2020-03-13 +Full library refactoring. + +### Added +- Support for multiple parallel request with `curl_multi` +- Support for PSR-7 Http Messages, PSR-17 Http Factories and PSR-18 Http Client +- `cms` value +- `language` to detect the page language +- `languages` to detect urls to versions in different languages +- `favicon` to detect small favicons (16 or 32px) +- `icon` to detect big icons (from 48px) + +### Changed +- Changed providers (oEmbed, Html, OpenGraph etc) by independent detectors (title, url, language etc). +- The `tags` value is renamed to `keywords` +- Use Psr standards instead custom interfaces. +- Improved tests using cached responses. + +### Removed +- Support for PHP<7.4 +- `type` value (is was very confusing) +- `images` value +- `providerImage` (use `favicon` or `icon` instead) +- Support for files (pdf, jpg, video, etc). + +[#332]: https://github.com/oscarotero/Embed/issues/332 +[#345]: https://github.com/oscarotero/Embed/issues/345 +[#346]: https://github.com/oscarotero/Embed/issues/346 +[#355]: https://github.com/oscarotero/Embed/issues/355 +[#356]: https://github.com/oscarotero/Embed/issues/356 +[#357]: https://github.com/oscarotero/Embed/issues/357 +[#364]: https://github.com/oscarotero/Embed/issues/364 +[#366]: https://github.com/oscarotero/Embed/issues/366 +[#375]: https://github.com/oscarotero/Embed/issues/375 +[#380]: https://github.com/oscarotero/Embed/issues/380 +[#384]: https://github.com/oscarotero/Embed/issues/384 +[#385]: https://github.com/oscarotero/Embed/issues/385 +[#386]: https://github.com/oscarotero/Embed/issues/386 +[#387]: https://github.com/oscarotero/Embed/issues/387 +[#388]: https://github.com/oscarotero/Embed/issues/388 +[#392]: https://github.com/oscarotero/Embed/issues/392 +[#394]: https://github.com/oscarotero/Embed/issues/394 +[#399]: https://github.com/oscarotero/Embed/issues/399 +[#405]: https://github.com/oscarotero/Embed/issues/405 +[#406]: https://github.com/oscarotero/Embed/issues/406 +[#412]: https://github.com/oscarotero/Embed/issues/412 +[#413]: https://github.com/oscarotero/Embed/issues/413 +[#427]: https://github.com/oscarotero/Embed/issues/427 +[#429]: https://github.com/oscarotero/Embed/issues/429 +[#430]: https://github.com/oscarotero/Embed/issues/430 +[#432]: https://github.com/oscarotero/Embed/issues/432 +[#433]: https://github.com/oscarotero/Embed/issues/433 +[#437]: https://github.com/oscarotero/Embed/issues/437 +[#450]: https://github.com/oscarotero/Embed/issues/450 +[#451]: https://github.com/oscarotero/Embed/issues/451 +[#452]: https://github.com/oscarotero/Embed/issues/452 +[#456]: https://github.com/oscarotero/Embed/issues/456 +[#459]: https://github.com/oscarotero/Embed/issues/459 +[#466]: https://github.com/oscarotero/Embed/issues/466 +[#467]: https://github.com/oscarotero/Embed/issues/467 +[#468]: https://github.com/oscarotero/Embed/issues/468 +[#473]: https://github.com/oscarotero/Embed/issues/473 +[#474]: https://github.com/oscarotero/Embed/issues/474 +[#480]: https://github.com/oscarotero/Embed/issues/480 +[#481]: https://github.com/oscarotero/Embed/issues/481 +[#494]: https://github.com/oscarotero/Embed/issues/494 +[#495]: https://github.com/oscarotero/Embed/issues/495 +[#496]: https://github.com/oscarotero/Embed/issues/496 +[#497]: https://github.com/oscarotero/Embed/issues/497 +[#498]: https://github.com/oscarotero/Embed/issues/498 +[#499]: https://github.com/oscarotero/Embed/issues/499 +[#501]: https://github.com/oscarotero/Embed/issues/501 +[#502]: https://github.com/oscarotero/Embed/issues/502 +[#506]: https://github.com/oscarotero/Embed/issues/506 +[#507]: https://github.com/oscarotero/Embed/issues/507 +[#514]: https://github.com/oscarotero/Embed/issues/514 +[#515]: https://github.com/oscarotero/Embed/issues/515 +[#525]: https://github.com/oscarotero/Embed/issues/525 +[#527]: https://github.com/oscarotero/Embed/issues/527 +[#529]: https://github.com/oscarotero/Embed/issues/529 +[#537]: https://github.com/oscarotero/Embed/issues/537 +[#540]: https://github.com/oscarotero/Embed/issues/540 +[#548]: https://github.com/oscarotero/Embed/issues/548 +[#551]: https://github.com/oscarotero/Embed/issues/551 +[#553]: https://github.com/oscarotero/Embed/issues/553 +[#555]: https://github.com/oscarotero/Embed/issues/555 +[#556]: https://github.com/oscarotero/Embed/issues/556 + +[4.4.17]: https://github.com/oscarotero/Embed/compare/v4.4.16...v4.4.17 +[4.4.16]: https://github.com/oscarotero/Embed/compare/v4.4.15...v4.4.16 +[4.4.15]: https://github.com/oscarotero/Embed/compare/v4.4.14...v4.4.15 +[4.4.14]: https://github.com/oscarotero/Embed/compare/v4.4.13...v4.4.14 +[4.4.13]: https://github.com/oscarotero/Embed/compare/v4.4.12...v4.4.13 +[4.4.12]: https://github.com/oscarotero/Embed/compare/v4.4.11...v4.4.12 +[4.4.11]: https://github.com/oscarotero/Embed/compare/v4.4.10...v4.4.11 +[4.4.10]: https://github.com/oscarotero/Embed/compare/v4.4.9...v4.4.10 +[4.4.9]: https://github.com/oscarotero/Embed/compare/v4.4.8...v4.4.9 +[4.4.8]: https://github.com/oscarotero/Embed/compare/v4.4.7...v4.4.8 +[4.4.7]: https://github.com/oscarotero/Embed/compare/v4.4.6...v4.4.7 +[4.4.6]: https://github.com/oscarotero/Embed/compare/v4.4.5...v4.4.6 +[4.4.5]: https://github.com/oscarotero/Embed/compare/v4.4.4...v4.4.5 +[4.4.4]: https://github.com/oscarotero/Embed/compare/v4.4.3...v4.4.4 +[4.4.3]: https://github.com/oscarotero/Embed/compare/v4.4.2...v4.4.3 +[4.4.2]: https://github.com/oscarotero/Embed/compare/v4.4.1...v4.4.2 +[4.4.1]: https://github.com/oscarotero/Embed/compare/v4.4.0...v4.4.1 +[4.4.0]: https://github.com/oscarotero/Embed/compare/v4.3.5...v4.4.0 +[4.3.5]: https://github.com/oscarotero/Embed/compare/v4.3.4...v4.3.5 +[4.3.4]: https://github.com/oscarotero/Embed/compare/v4.3.3...v4.3.4 +[4.3.3]: https://github.com/oscarotero/Embed/compare/v4.3.2...v4.3.3 +[4.3.2]: https://github.com/oscarotero/Embed/compare/v4.3.1...v4.3.2 +[4.3.1]: https://github.com/oscarotero/Embed/compare/v4.3.0...v4.3.1 +[4.3.0]: https://github.com/oscarotero/Embed/compare/v4.2.7...v4.3.0 +[4.2.7]: https://github.com/oscarotero/Embed/compare/v4.2.6...v4.2.7 +[4.2.6]: https://github.com/oscarotero/Embed/compare/v4.2.5...v4.2.6 +[4.2.5]: https://github.com/oscarotero/Embed/compare/v4.2.4...v4.2.5 +[4.2.4]: https://github.com/oscarotero/Embed/compare/v4.2.3...v4.2.4 +[4.2.3]: https://github.com/oscarotero/Embed/compare/v4.2.2...v4.2.3 +[4.2.2]: https://github.com/oscarotero/Embed/compare/v4.2.1...v4.2.2 +[4.2.1]: https://github.com/oscarotero/Embed/compare/v4.2.0...v4.2.1 +[4.2.0]: https://github.com/oscarotero/Embed/compare/v4.1.1...v4.2.0 +[4.1.1]: https://github.com/oscarotero/Embed/compare/v4.1.0...v4.1.1 +[4.1.0]: https://github.com/oscarotero/Embed/compare/v4.0.0...v4.1.0 +[4.0.0]: https://github.com/oscarotero/Embed/releases/tag/v4.0.0 diff --git a/LICENSE b/LICENSE index c811c59a..2385321a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Oscar Otero Marzoa +Copyright (c) 2017 Oscar Otero Marzoa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index acf26eba..538a0c46 100644 --- a/README.md +++ b/README.md @@ -1,286 +1,360 @@ -# Embed +# Embed -[![Build Status](https://travis-ci.org/oscarotero/Embed.svg?branch=master)](https://travis-ci.org/oscarotero/Embed) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/oscarotero/Embed/badges/quality-score.png?s=79e37032db280b9795388124c030dcf4309343d1)](https://scrutinizer-ci.com/g/oscarotero/Embed/) -[![Reference Status](https://www.versioneye.com/php/embed:embed/reference_badge.svg?style=flat)](https://www.versioneye.com/php/embed:embed/references) -[![Latest Stable Version](https://poser.pugx.org/embed/embed/v/stable)](https://packagist.org/packages/embed/embed) -[![Total Downloads](https://poser.pugx.org/embed/embed/downloads)](https://packagist.org/packages/embed/embed) -[![Monthly Downloads](https://poser.pugx.org/embed/embed/d/monthly)](https://packagist.org/packages/embed/embed) -[![License](https://poser.pugx.org/embed/embed/license)](https://packagist.org/packages/embed/embed) -[![Support via Gittip](https://img.shields.io/gratipay/oscarotero.svg)](https://www.gratipay.com/oscarotero/) -[![SensioLabsInsight](https://insight.sensiolabs.com/projects/f0beab9f-fe41-47db-8806-373f80c50f9e/big.png)](https://insight.sensiolabs.com/projects/f0beab9f-fe41-47db-8806-373f80c50f9e) +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Total Downloads][ico-downloads]][link-packagist] +[![Monthly Downloads][ico-m-downloads]][link-packagist] +[![Software License][ico-license]](LICENSE) PHP library to get information from any web page (using oembed, opengraph, twitter-cards, scrapping the html, etc). It's compatible with any web service (youtube, vimeo, flickr, instagram, etc) and has adapters to some sites like (archive.org, github, facebook, etc). Requirements: -* PHP 5.4+ +* PHP 7.4+ * Curl library installed +* PSR-17 implementation. By default these libraries are detected automatically: + * [laminas/laminas-diactoros](https://github.com/laminas/laminas-diactoros) + * [guzzle/psr7](https://github.com/guzzle/psr7) + * [nyholm/psr7](https://github.com/Nyholm/psr7) + * [sunrise/http-message](https://github.com/sunrise-php/http-message) -If you need PHP 5.3 support, use the 1.x version (but not maintained anymore) +> If you need PHP 5.5-7.3 support, [use the 3.x version](https://github.com/oscarotero/Embed/tree/v3.x) ## Online demo -http://oscarotero.com/embed2/demo +Run `php -S localhost:8888 demo/index.php` + +## Video Tutorial + [](https://youtu.be/4YCLRpKY1cs) + + +## Installation + +This package is installable and autoloadable via Composer as [embed/embed](https://packagist.org/packages/embed/embed). + +``` +$ composer require embed/embed +``` ## Usage ```php -//Load library (if you don't have composer or any psr-4 compatible loader): -include('src/autoloader.php'); +use Embed\Embed; + +$embed = new Embed(); //Load any url: -$info = Embed\Embed::create('https://www.youtube.com/watch?v=PP1xn5wHtxE'); +$info = $embed->get('https://www.youtube.com/watch?v=PP1xn5wHtxE'); //Get content info $info->title; //The page title $info->description; //The page description $info->url; //The canonical url -$info->type; //The page type (link, video, image, rich) -$info->tags; //The page keywords (tags) +$info->keywords; //The page keywords -$info->images; //List of all images found in the page -$info->image; //The image choosen as main image -$info->imageWidth; //The width of the main image -$info->imageHeight; //The height of the main image +$info->image; //The thumbnail or main image -$info->code; //The code to embed the image, video, etc -$info->width; //The width of the embed code -$info->height; //The height of the embed code -$info->aspectRatio; //The aspect ratio (width/height) +$info->code->html; //The code to embed the image, video, etc +$info->code->width; //The exact width of the embed code (if exists) +$info->code->height; //The exact height of the embed code (if exists) +$info->code->ratio; //The percentage of height / width to emulate the aspect ratio using paddings. -$info->authorName; //The (video/article/image/whatever) author +$info->authorName; //The resource author $info->authorUrl; //The author url -$info->providerName; //The provider name of the page (youtube, twitter, instagram, etc) +$info->cms; //The cms used +$info->language; //The language of the page +$info->languages; //The alternative languages + +$info->providerName; //The provider name of the page (Youtube, Twitter, Instagram, etc) $info->providerUrl; //The provider url -$info->providerIcons; //All provider icons found in the page -$info->providerIcon; //The icon choosen as main icon +$info->icon; //The big icon of the site +$info->favicon; //The favicon of the site (an .ico file or a png with up to 32x32px) -$info->publishedDate; //The (video/article/image/whatever) published date +$info->publishedTime; //The published time of the resource +$info->license; //The license url of the resource +$info->feeds; //The RSS/Atom feeds ``` -## Customization +## Parallel multiple requests -You can set some options using an array as second argument. In this array you can configure the adapters, providers, resolvers, etc. +```php +use Embed\Embed; -### The adapter +$embed = new Embed(); -The adapter is the class that get all information of the page from the providers and choose the best result for each value. For example, a page can provide multiple titles from opengraph, twitter cards, oembed, the `` html element, etc, so the adapter get all this titles and choose the best one. +//Load multiple urls asynchronously: +$infos = $embed->getMulti( + 'https://www.youtube.com/watch?v=PP1xn5wHtxE', + 'https://twitter.com/carlosmeixidefl/status/1230894146220625933', + 'https://en.wikipedia.org/wiki/Tordoia', +); -Embed has an generic adapter called "Webpage" to use in any web but has also some specific adapters for sites like archive.org, facebook, google, github, spotify, etc, that provides information using their own apis, or have any other special issue. +foreach ($infos as $info) { + echo $info->title; +} +``` -You can configure these adapters and even create your own adapter, that must implement the `Embed\Adapters\AdapterInterface`. +## Document +The document is the object that store the html code of the page. You can use it to extract extra info from the html code: -The available options for the adapters are: +```php +//Get the document object +$document = $info->getDocument(); -* minImageWidth (int): Minimal image width used to choose the main image -* minImageHeight (int): Minimal image height used to choose the main image -* imagesBlacklist (array): Images that you don't want to be used. Could be plain text or [Url](https://github.com/oscarotero/Embed/blob/master/src/Url.php) match pattern. -* getBiggerImage (bool): Choose the bigger image as the main image (instead the first found, that usually is the most relevant). -* getBiggerIcon (bool): The same than getBiggerImage but used to choose the main icon +$document->link('image_src'); //Returns the href of a <link> +$document->getDocument(); //Returns the DOMDocument instance +$html = (string) $document; //Returns the html code -```php -$config = [ - 'adapter' => [ - 'class' => 'MyCustomClass', //Your custom adapter - - 'config' => [ - 'minImageWidth' => 16, - 'minImageHeight' => 16, - 'imagesBlacklist' => null, - 'getBiggerImage' => false, - 'getBiggerIcon' => false, - ] - ] -]; +$document->select('.//h1'); //Search ``` -### The providers +You can perform xpath queries in order to select specific elements. A search always return an instance of a `Embed\QueryResult`: -The providers get the data from different sources. Each source has it's own provider. For example, there is a provider for open graph, other for twitter cards, for oembed, html, etc. The providers that receive options are: - -#### oembed +```php +//Search the A elements +$result = $document->select('.//a'); -Used to get data from oembed api if it's available. It accepts two options: +//Filter the results +$result->filter(fn ($node) => $node->getAttribute('href')); -* parameters (array): Extra query parameters to send with the oembed request -* embedlyKey (string): If it's defined, use embed.ly api as fallback oembed provider. -* iframelyKey (string): If it's defined, use iframe.ly api as fallback oembed provider. +$id = $result->str('id'); //Return the id of the first result as string +$text = $result->str(); //Return the content of the first result -#### html +$ids = $result->strAll('id'); //Return an array with the ids of all results as string +$texts = $result->strAll(); //Return an array with the content of all results as string -Used to get data directly from the html code of the page: +$tabindex = $result->int('tabindex'); //Return the tabindex attribute of the first result as integer +$number = $result->int(); //Return the content of the first result as integer -* maxImages (int): Max number of images fetched from the html code (searching for the `<img>` elements). By default is -1 (no limit). Use 0 to no get images. +$href = $result->url('http://github.com/href'); //Return the href attribute of the first result as url (converts relative urls to absolutes) +$url = $result->url(); //Return the content of the first result as url -#### facebook +$node = $result->node(); //Return the first node found (DOMElement) +$nodes = $result->nodes(); //Return all nodes found +``` -This provider is used only for facebook pages, to get information from the [graph api](https://developers.facebook.com/docs/graph-api) +## Metas -* key (string): the key used +For convenience, the object `Metas` stores the value of all `<meta>` elements located in the html, so you can get the values easier. The key of every meta is get from the `name`, `property` or `itemprop` attributes and the value is get from `content`. -#### google +```php +//Get the Metas object +$metas = $info->getMetas(); + +$metas->all(); //Return all values +$metas->get('og:title'); //Return a key value +$metas->str('og:title'); //Return the value as string (remove html tags) +$metas->html('og:description'); //Return the value as html +$metas->int('og:video:width'); //Return the value as integer +$metas->url('/service/og:url'); //Return the value as full url (converts relative urls to absolutes) +``` -This provider is used only for google maps, to generate the embed code [using the embed api](https://developers.google.com/maps/documentation/embed/) +## OEmbed -* key (string): the key used +In addition to the html and metas, this library uses [oEmbed](https://oembed.com/) endpoints to get additional data. You can get this data as following: -#### soundcloud +```php +//Get the oEmbed object +$oembed = $info->getOEmbed(); + +$oembed->all(); //Return all raw data +$oembed->get('title'); //Return a key value +$oembed->str('title'); //Return the value as string (remove html tags) +$oembed->html('html'); //Return the value as html +$oembed->int('width'); //Return the value as integer +$oembed->http://github.com/url('url'); //Return the value as full url (converts relative urls to absolutes) +``` -Used only for soundcloud pages, to get information using its api. +Additional oEmbed parameters (like instagrams `hidecaption`) can also be provided: +```php +$embed = new Embed(); -* key (string): to get info from soundcloud API. +$result = $embed->get('https://www.instagram.com/p/B_C0wheCa4V/'); +$result->setSettings([ + 'oembed:query_parameters' => ['hidecaption' => true] +]); +$oembed = $info->getOEmbed(); +``` +## LinkedData -### The request resolver +Another API available by default, used to extract info using the [JsonLD](https://www.w3.org/TR/json-ld/) schema. -Embed uses the `Embed\RequestResolvers\Curl` class to resolve all requests using the curl library. You can set options to the curl request or use your custom resolver creating a class implementing the `Embed\RequestResolvers\RequestResolverInterface`. +```php +//Get the linkedData object +$ld = $info->getLinkedData(); + +$ld->all(); //Return all data +$ld->get('name'); //Return a key value +$ld->str('name'); //Return the value as string (remove html tags) +$ld->html('description'); //Return the value as html +$ld->int('width'); //Return the value as integer +$ld->http://github.com/url('url'); //Return the value as full url (converts relative urls to absolutes) +``` -The resolver configuration is defined under the "resolver" key and it has two options: +## Other APIs -* class: Your custom class name if you want to use your own implementation -* config: The options passed to the class. If you use the default curl class, the config are the same than the [curl_setopt PHP function](http://php.net/manual/en/function.curl-setopt.php) +Some sites like Wikipedia or Archive.org provide a custom API that is used to fetch more reliable data. You can get the API object with the method `getApi()` but note that not all results have this method. The Api object has the same methods than oEmbed: ```php -// CURL -$config = [ - 'resolver' => [ - 'class' => 'Embed\\RequestResolvers\\Curl', // The default resolver used - - 'config' => [ - CURLOPT_MAXREDIRS => 20, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_TIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - CURLOPT_ENCODING => '', - CURLOPT_AUTOREFERER => true, - CURLOPT_USERAGENT => 'Embed PHP Library', - CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, - ] - ] -]; - -// Guzzle (5.x) -$config = [ - 'resolver' => [ - 'class' => 'Embed\\RequestResolvers\\Guzzle5', // Guzzle5 resolver used - - 'config' => [ - // optional: if you need to use your custom Guzzle instance - 'client' => $myGuzzleClient, - ] - ] -]; +//Get the API object +$api = $info->getApi(); + +$api->all(); //Return all raw data +$api->get('title'); //Return a key value +$api->str('title'); //Return the value as string (remove html tags) +$api->html('html'); //Return the value as html +$api->int('width'); //Return the value as integer +$api->http://github.com/url('url'); //Return the value as full url (converts relative urls to absolutes) ``` -[You can see here](https://github.com/oscarotero/Embed/tree/master/src/RequestResolvers) the RequestResolvers included. +## Extending Embed -### Image info +Depending of your needs, you may want to extend this library with extra features or change the way it makes some operations. -To check the images and get their mimetype and dimmensions, we have the class `Embed\ImageInfo\Curl`. This class uses curl to make request, get the first bytes to get the image type and dimmensions and close the connection. So the image wont be downloaded entirely, just until the downloaded data is enought to get this information. +### PSR -Like the resolver class, you can provide your own image class (it must implement the `Embed\ImageInfo\ImageInfoInterface`) and/or change the configuration. The available options are the same: +Embed use some PSR standards to be the most interoperable possible: -* class: Your custom class name if you want to use your own implementation -* config: The options passed to the class. If you use the default curl class, the config are the same than the [curl_setopt PHP function](http://php.net/manual/en/function.curl-setopt.php) +- [PSR-7](https://www.php-fig.org/psr/psr-7/) Standard interfaces to represent http requests, responses and uris +- [PSR-17](https://www.php-fig.org/psr/psr-17/) Standard factories to create PSR-7 objects +- [PSR-18](https://www.php-fig.org/psr/psr-18/) Standard interface to send a http request and return a response +Embed comes with a CURL client compatible with PSR-18 but you need to install a PSR-7 / PSR-17 library. [Here you can see a list of popular libraries](https://github.com/middlewares/awesome-psr15-middlewares#psr-7-implementations) and the library can detect automatically 'laminas\diactoros', 'guzzleHttp\psr7', 'slim\psr7', 'nyholm\psr7' and 'sunrise\http' (in this order). If you want to use a different PSR implementation, you can do it in this way: ```php -//CURL -$config = [ - 'image' => [ - 'class' => 'Embed\\ImageInfo\\Curl', //The default imageInfo used - - 'config' => [ - CURLOPT_MAXREDIRS => 20, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_TIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - CURLOPT_ENCODING => '', - CURLOPT_AUTOREFERER => true, - CURLOPT_USERAGENT => 'Embed PHP Library', - CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, - ] - ] -]; - -// Guzzle (5.x) -$config = [ - 'image' => [ - 'class' => 'Embed\\ImageInfo\\Guzzle5', - - 'config' => [ - 'client' => $myGuzzleClient, - ] - ] -]; +use Embed\Embed; +use Embed\Http\Crawler; + +$client = new CustomHttpClient(); +$requestFactory = new CustomRequestFactory(); +$uriFactory = new CustomUriFactory(); + +//The Crawler is responsible for perform http queries +$crawler = new Crawler($client, $requestFactory, $uriFactory); + +//Create an embed instance passing the Crawler +$embed = new Embed($crawler); ``` -[You can see here](https://github.com/oscarotero/Embed/tree/master/src/ImageInfo) the ImageInfo implementations included. +### Adapters + +There are some sites with special needs: because they provide public APIs that allows to extract more info (like Wikipedia or Archive.org) or because we need to change how to extract the data in this particular site. For all that cases we have the adapters, that are classes extending the default classes to provide extra functionality. + +Before creating an adapter, you need to understand how Embed work: when you execute this code, you get a `Extractor` class +```php +//Get the Extractor with all info +$info = $embed->get($url); + +//The extractor have document and oembed: +$document = $info->getDocument(); +$oembed = $info->getOEmbed(); +``` -### Configuration example +The `Extractor` class has many `Detectors`. Each detector is responsible to detect a specific piece of info. For example, there's a detector for the title, other for description, image, code, etc. +So, an adapter is basically an extractor created specifically for a site. It can contains also custom detectors or apis. If you see the `src/Adapters` folder you can see all adapters. + +If you create an adapter, you need also register to Embed, so it knows in which website needs to use. To do that, there's the `ExtractorFactory` object, that is responsible for instantiate the right extractor for each site. ```php -$config = [ - 'adapter' => [ - 'config' => [ - 'minImageWidth' => 16, - 'minImageHeight' => 16, - 'imagesBlacklist' => [ - 'http://example.com/full/path/to/image.jpg', - 'http?://test.*/*.png/', - '*/bad_image.gif' - ] - ] - ], - 'providers' => [ - 'oembed' => [ - 'parameters' => [], - 'embedlyKey' => null - ], - 'html' => [ - 'maxImages' => 3 - ], - 'facebook' => [ - 'key' => 'our-access-token' - ] - ], - 'resolver' => [ - 'config' => [ - CURLOPT_USERAGENT => 'My spider', - CURLOPT_MAXREDIRS => 3 - ] - ] - 'image' => [ - 'class' => 'App\\MyImageInfoClass' - ] -]; +use Embed\Embed; + +$embed = new Embed(); + +$factory = $embed->getExtractorFactory(); + +//Use this MySite adapter for mysite.com +$factory->addAdapter('mysite.com', MySite::class); + +//Remove the adapter for pinterest.com, so it will use the default extractor +$factory->removeAdapter('pinterest.com'); + +//Change the default extractor +$factory->setDefault(CustomExtractor::class); ``` -### Access to more data +### Detectors -As said before, the adapter get the data from all providers and choose the best values. But you can get the data directly from the providers, useful if you want to get the specific value returned by any provider. +Embed comes with several predefined detectors, but you may want to change or add more. Just create a class extending `Embed\Detectors\Detector` class and register it in the extractor factory. For example: ```php use Embed\Embed; +use Embed\Detectors\Detector; + +class Robots extends Detector +{ + public function detect(): ?string + { + $response = $this->extractor->getResponse(); + $metas = $this->extractor->getMetas(); + + return $response->getHeaderLine('x-robots-tag'), + ?: $metas->str('robots'); + } +} + +//Register the detector +$embed = new Embed(); +$embed->getExtractorFactory()->addDetector('robots', Robots::class); + +//Use it +$info = $embed->get('http://example.com/'); +$robots = $info->robots; +``` -//Get the info -$info = Embed::create('https://www.youtube.com/watch?v=PP1xn5wHtxE'); +### Settings -//Get the oembed provider -$oembed = $info->getProvider('oembed'); +If you need to pass settings to the CurlClient to perform http queries: -//Get the oembed title: -echo $oembed->getTitle(); +```php +use Embed\Embed; +use Embed\Http\Crawler; +use Embed\Http\CurlClient; + +$client = new CurlClient(); +$client->setSettings([ + 'cookies_path' => $cookies_path, + 'ignored_errors' => [18], + 'max_redirs' => 3, // see CURLOPT_MAXREDIRS + 'connect_timeout' => 2, // see CURLOPT_CONNECTTIMEOUT + 'timeout' => 2, // see CURLOPT_TIMEOUT + 'ssl_verify_host' => 2, // see CURLOPT_SSL_VERIFYHOST + 'ssl_verify_peer' => 1, // see CURLOPT_SSL_VERIFYPEER + 'follow_location' => true, // see CURLOPT_FOLLOWLOCATION + 'user_agent' => 'Mozilla', // see CURLOPT_USERAGENT +]); + +$embed = new Embed(new Crawler($client)); +``` + +If you need to pass settings to your detectors, you can add settings to the `ExtractorFactory`: -//Get any value returned by oembed api -echo $oembed->bag->get('author_name'); +```php +use Embed\Embed; + +$embed = new Embed(); +$embed->setSettings([ + 'oembed:query_parameters' => [], //Extra parameters send to oembed + 'twitch:parent' => 'example.com', //Required to embed twitch videos as iframe + 'facebook:token' => '1234|5678', //Required to embed content from Facebook + 'instagram:token' => '1234|5678', //Required to embed content from Instagram + 'twitter:token' => 'asdf', //Improve the data from twitter +]); +$info = $embed->get($url); ``` + +Note: The built-in detectors does not require settings. This feature is only for convenience if you create a specific detector that requires settings. + +--- + +[ico-version]: https://poser.pugx.org/embed/embed/v/stable +[ico-license]: https://poser.pugx.org/embed/embed/license +[ico-downloads]: https://poser.pugx.org/embed/embed/downloads +[ico-m-downloads]: https://poser.pugx.org/embed/embed/d/monthly + +[link-packagist]: https://packagist.org/packages/embed/embed diff --git a/composer.json b/composer.json index 7ba59288..993f65e5 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,13 @@ "name": "embed/embed", "type": "library", "description": "PHP library to retrieve page info using oembed, opengraph, etc", - "keywords": ["oembed", "opengraph", "twitter cards", "embed", "embedly"], + "keywords": [ + "oembed", + "opengraph", + "twitter cards", + "embed", + "embedly" + ], "homepage": "https://github.com/oscarotero/Embed", "license": "MIT", "authors": [ @@ -18,20 +24,52 @@ "issues": "https://github.com/oscarotero/Embed/issues" }, "require": { - "php": ">=5.4.0", - "ext-curl": "*" + "php": "^7.4|^8", + "ext-curl": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-mbstring": "*", + "composer/ca-bundle": "^1.0", + "oscarotero/html-parser": "^0.1.4", + "psr/http-message": "^1.0|^2.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "ml/json-ld": "^1.1" }, "require-dev": { - "guzzlehttp/guzzle": "5.x", - "sstalle/php7cc": "^1.0", - "phpunit/phpunit": "*" + "phpunit/phpunit": "^9.0", + "friendsofphp/php-cs-fixer": "^2.0", + "nyholm/psr7": "^1.2", + "oscarotero/php-cs-fixer-config": "^1.0", + "brick/varexporter": "^0.3.1", + "symfony/css-selector": "^5.0", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-strict-rules": "^2.0" }, "suggest": { - "guzzlehttp/guzzle@5.x": "To use Guzzle5 request resolver" + "symfony/css-selector": "If you want to get elements using css selectors" }, "autoload": { "psr-4": { "Embed\\": "src" + }, + "files": [ + "src/functions.php" + ] + }, + "autoload-dev": { + "psr-4": { + "Embed\\Tests\\": "tests/" } + }, + "scripts": { + "demo": "php -S localhost:8888 demo/index.php", + "test": "phpunit", + "cs-fix": "php-cs-fixer fix", + "phpstan": "phpstan --memory-limit=-1", + "update-resources": [ + "php scripts/update-oembed.php", + "php scripts/update-suffix.php" + ] } } diff --git a/demo/index.php b/demo/index.php index 6fb9c454..850aba98 100644 --- a/demo/index.php +++ b/demo/index.php @@ -2,43 +2,70 @@ ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); -include '../src/autoloader.php'; +include __DIR__.'/../vendor/autoload.php'; -function get($name, $default = '') +function getUrl(): ?string { - if (!isset($_GET[$name])) { - return $default; + $skipParams = ['url', 'settings']; + $url = getParam('url'); + + if (!$url) { + return null; } - if ($name === 'url') { - if (!filter_var($_GET['url'], FILTER_VALIDATE_URL)) { - return 'http://donottrytoxss.invalid/'; + //fix for unescaped urls + foreach ($_GET as $name => $value) { + if (in_array($name, $skipParams, true)) { + continue; } + + $url .= "&{$name}={$value}"; } - return $_GET[$name]; + return $url; +} + +function getParam(string $paramName): ?string +{ + return $_GET[$paramName] ?? null; } -function getEscaped($name, $default = '') +function getJsonSettings(): array { - return htmlspecialchars(get($name, $default), ENT_QUOTES, 'UTF-8'); + $jsonString = getParam('settings') ?: '{}'; + return json_decode($jsonString, true, 512, JSON_THROW_ON_ERROR); } -function printAny($text) +function getEscapedUrl(): ?string +{ + $url = getUrl(); + return $url ? htmlspecialchars($url, ENT_QUOTES, 'UTF-8') : null; +} + +function printAny($text): void { if (is_array($text)) { printArray($text); } else { - printText($text); + printText((string) $text); + } +} + +function printText(?string $text): void +{ + if ($text) { + echo htmlspecialchars($text, ENT_IGNORE); } } -function printText($text) +function printDatetime(?DateTimeInterface $date): void { - echo htmlspecialchars($text, ENT_IGNORE); + if ($date) { + echo $date->format('Y-m-d H:i:s'); + } } -function printImage($image) +function printImage(?string $image): void { if ($image) { echo <<<EOT @@ -48,7 +75,7 @@ function printImage($image) } } -function printUrl($url) +function printUrl(?string $url): void { if ($url) { echo <<<EOT @@ -57,14 +84,25 @@ function printUrl($url) } } -function printArray($array) +function printArray(?array $array): void { if ($array) { echo '<pre>'.htmlspecialchars(print_r($array, true), ENT_IGNORE).'</pre>'; } } -function printCode($code, $asHtml = true) +function printHeaders(array $array): void +{ + $headers = []; + + foreach ($array as $name => $values) { + $headers[$name] = implode(', ', $values); + } + + printArray($headers); +} + +function printCode(?string $code, bool $asHtml = true): void { if ($asHtml) { echo $code; @@ -75,47 +113,25 @@ function printCode($code, $asHtml = true) } } -$providerData = [ - 'title' => 'printText', - 'description' => 'printText', - 'url' => 'printUrl', - 'type' => 'printText', - 'tags' => 'printArray', - 'imagesUrls' => 'printArray', - 'code' => 'printCode', - 'source' => 'printUrl', - 'width' => 'printText', - 'height' => 'printText', - 'authorName' => 'printText', - 'authorUrl' => 'printUrl', - 'providerIconsUrls' => 'printArray', - 'providerName' => 'printText', - 'providerUrl' => 'printUrl', - 'publishedTime' => 'printText', -]; - -$adapterData = [ +$detectors = [ 'title' => 'printText', 'description' => 'printText', 'url' => 'printUrl', - 'type' => 'printText', - 'tags' => 'printArray', + 'keywords' => 'printArray', 'image' => 'printImage', - 'imageWidth' => 'printText', - 'imageHeight' => 'printText', - 'images' => 'printArray', 'code' => 'printCode', - 'source' => 'printUrl', - 'width' => 'printText', - 'height' => 'printText', - 'aspectRatio' => 'printText', + 'feeds' => 'printArray', 'authorName' => 'printText', 'authorUrl' => 'printUrl', - 'providerIcon' => 'printImage', - 'providerIcons' => 'printArray', + 'icon' => 'printImage', + 'favicon' => 'printImage', 'providerName' => 'printText', 'providerUrl' => 'printUrl', - 'publishedTime' => 'printText', + 'publishedTime' => 'printDatetime', + 'license' => 'printUrl', + 'cms' => 'printText', + 'language' => 'printText', + 'languages' => 'printArray', ]; ?> @@ -127,7 +143,38 @@ function printCode($code, $asHtml = true) <title>Embed tests - + @@ -135,95 +182,134 @@ function printCode($code, $asHtml = true)
+
+
- +
    Get the source code from Github -    -    - or the bookmarklet
- -
+ +

Result:

getCrawler()->addDefaultHeaders([ + 'Accept-Language' => 'en-US,en;q=0.2', + 'Cache-Control' => 'max-age=0,no-cache', + ]); + + $embed->setSettings( + array_merge( + [ + 'twitch:parent' => $_SERVER['SERVER_NAME'] === 'localhost' ? null : $_SERVER['SERVER_NAME'], + ], + getJsonSettings() + ) + ); + $info = $embed->get(getUrl()); } catch (Exception $exception) { - echo '

'.$exception->getMessage().'

'; - echo '
'; - echo ''; - echo ''; + echo '
';
+                echo $exception;
+                echo '
'; die(); } ?> - $fn): ?> + $fn) : ?> - +
$name); ?>
-
- -
- -
- getAllProviders() as $providerName => $provider): ?> -

provider

- - - $fn): ?> - - - - - - - - - - - - api)): ?> - - - - - - -
{'get'.$name}(), false); ?>
All data collectedbag->getAll()); ?>
Data provider by the APIapi->getAll()); ?>
- - -

Http request info

- - - getRequest()->getRequestInfo() as $name => $value): ?> - - - - - -
- -

Content

- -
-                    getRequest()->getContent()); ?>
-                
-
- - +
+ View all collected data + +
+

OEmbed data

+ + + + + + + + + + + +
EndpointgetOEmbed()->getEndpoint()); ?>
All data collectedgetOEmbed()->all()); ?>
+ +

Meta data

+ + + + + + +
All data collectedgetMetas()->all()); ?>
+ +

Linked data

+ + + + + + +
All data collectedgetLinkedData()->all()); ?>
+ + +

API data

+ + + + + + + + + + + +
EndpointgetApi()->getEndpoint()); ?>
All data collectedgetApi()->all()); ?>
+ + +

HTML content

+ +
+                        getResponse()->getBody()); ?>
+                    
+
+
+ + + - diff --git a/demo/sources.php b/demo/sources.php deleted file mode 100644 index 1e79dbe8..00000000 --- a/demo/sources.php +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - Sources tests - - - - -
-
- - -
-
- - -
- - - - -

The url is not valid!

- - - -

providerUrl; ?>

- - Test
- Source url - - - - -
- - - - - - -
Content -
request->getContent(), ENT_IGNORE); ?>
-
- - - - diff --git a/demo/styles.css b/demo/styles.css deleted file mode 100644 index e13d2675..00000000 --- a/demo/styles.css +++ /dev/null @@ -1,106 +0,0 @@ -body { - font-family: Helvetica, Arial, sans-serif; - min-width: 650px; - margin: 0; - padding: 0; -} -a { - color: inherit; - font-size: 0.9em; -} -a:hover { - text-decoration: none; -} -img { - display: block; - margin-bottom: 0.5em; -} -pre { - overflow: auto; - background: #EEE; - padding: 1em; -} - -/* form */ -form { - background: #EEE; - border-bottom: solid 1px #DDD; - color: #666; - padding: 3em 1.5em; -} -fieldset { - border: none; - padding: 0; -} -label { - display: block; - cursor: pointer; - font-weight: bold; -} -input[type="url"], -input[type="number"], -input[type="text"] { - border: none; - background: white; - border-radius: 2px; - box-sizing: border-box; - width: 100%; - margin: 5px 0; -} -input[type="number"] { - width: 50px; -} -input[type="url"] { - font-size: 1.3em; - padding: 0.5em; - color: #666; -} -button { - font-size: 1.6rem; - font-weight: bold; - font-family: Arial; - background: yellowgreen; - border: none; - border-radius: 2px; - padding: 0.2em 1em; - cursor: pointer; - margin-top: 5px; -} -button:hover { - background: black; - color: white; -} - -/* result */ -section { - padding: 1.5em; -} -section h1, section h2 { - font-size: 2em; - color: #666; - letter-spacing: -0.02em; -} -section h2 { - margin-top: 3em; -} - -table { - text-align: left; - width: 100%; - table-layout: fixed; -} -th, td { - vertical-align: top; - padding: 0.5em 1em 0.5em 0; - border-top: solid 1px #DDD; -} -th { - width: 200px; -} -#advanced-data { - display: none; -} -.view-advanced-data { - margin: 2em 0; - text-align: center; -} \ No newline at end of file diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 00000000..e989bd1a --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,15 @@ +includes: + - vendor/phpstan/phpstan-strict-rules/rules.neon + +parameters: + level: max + paths: + - src +# - tests + excludePaths: + - tests/cache + - tests/fixtures + checkMissingCallableSignature: true + checkUninitializedProperties: true + checkTooWideReturnTypesInProtectedAndPublicMethods: true + checkImplicitMixed: true diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 5116ceb2..00000000 --- a/phpunit.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - ./tests/ - - - diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 00000000..d8e22e25 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + tests + + + + + ignore + + + diff --git a/scripts/suffix.dat b/scripts/suffix.dat new file mode 100644 index 00000000..897be7a1 --- /dev/null +++ b/scripts/suffix.dat @@ -0,0 +1,11607 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// ===BEGIN ICANN DOMAINS=== + +// ac : https://en.wikipedia.org/wiki/.ac +ac +com.ac +edu.ac +gov.ac +net.ac +mil.ac +org.ac + +// ad : https://en.wikipedia.org/wiki/.ad +ad +nom.ad + +// ae : https://en.wikipedia.org/wiki/.ae +// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php +ae +co.ae +net.ae +org.ae +sch.ae +ac.ae +gov.ae +mil.ae + +// aero : see https://www.information.aero/index.php?id=66 +aero +accident-investigation.aero +accident-prevention.aero +aerobatic.aero +aeroclub.aero +aerodrome.aero +agents.aero +aircraft.aero +airline.aero +airport.aero +air-surveillance.aero +airtraffic.aero +air-traffic-control.aero +ambulance.aero +amusement.aero +association.aero +author.aero +ballooning.aero +broker.aero +caa.aero +cargo.aero +catering.aero +certification.aero +championship.aero +charter.aero +civilaviation.aero +club.aero +conference.aero +consultant.aero +consulting.aero +control.aero +council.aero +crew.aero +design.aero +dgca.aero +educator.aero +emergency.aero +engine.aero +engineer.aero +entertainment.aero +equipment.aero +exchange.aero +express.aero +federation.aero +flight.aero +freight.aero +fuel.aero +gliding.aero +government.aero +groundhandling.aero +group.aero +hanggliding.aero +homebuilt.aero +insurance.aero +journal.aero +journalist.aero +leasing.aero +logistics.aero +magazine.aero +maintenance.aero +media.aero +microlight.aero +modelling.aero +navigation.aero +parachuting.aero +paragliding.aero +passenger-association.aero +pilot.aero +press.aero +production.aero +recreation.aero +repbody.aero +res.aero +research.aero +rotorcraft.aero +safety.aero +scientist.aero +services.aero +show.aero +skydiving.aero +software.aero +student.aero +trader.aero +trading.aero +trainer.aero +union.aero +workinggroup.aero +works.aero + +// af : http://www.nic.af/help.jsp +af +gov.af +com.af +org.af +net.af +edu.af + +// ag : http://www.nic.ag/prices.htm +ag +com.ag +org.ag +net.ag +co.ag +nom.ag + +// ai : http://nic.com.ai/ +ai +off.ai +com.ai +net.ai +org.ai + +// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31 +al +com.al +edu.al +gov.al +mil.al +net.al +org.al + +// am : https://en.wikipedia.org/wiki/.am +am + +// ao : https://en.wikipedia.org/wiki/.ao +// http://www.dns.ao/REGISTR.DOC +ao +ed.ao +gv.ao +og.ao +co.ao +pb.ao +it.ao + +// aq : https://en.wikipedia.org/wiki/.aq +aq + +// ar : https://nic.ar/normativa-vigente.xhtml +ar +com.ar +edu.ar +gob.ar +gov.ar +int.ar +mil.ar +net.ar +org.ar +tur.ar + +// arpa : https://en.wikipedia.org/wiki/.arpa +// Confirmed by registry 2008-06-18 +arpa +e164.arpa +in-addr.arpa +ip6.arpa +iris.arpa +uri.arpa +urn.arpa + +// as : https://en.wikipedia.org/wiki/.as +as +gov.as + +// asia : https://en.wikipedia.org/wiki/.asia +asia + +// at : https://en.wikipedia.org/wiki/.at +// Confirmed by registry 2008-06-17 +at +ac.at +co.at +gv.at +or.at + +// au : https://en.wikipedia.org/wiki/.au +// http://www.auda.org.au/ +au +// 2LDs +com.au +net.au +org.au +edu.au +gov.au +asn.au +id.au +// Historic 2LDs (closed to new registration, but sites still exist) +info.au +conf.au +oz.au +// CGDNs - http://www.cgdn.org.au/ +act.au +nsw.au +nt.au +qld.au +sa.au +tas.au +vic.au +wa.au +// 3LDs +act.edu.au +nsw.edu.au +nt.edu.au +qld.edu.au +sa.edu.au +tas.edu.au +vic.edu.au +wa.edu.au +// act.gov.au Bug 984824 - Removed at request of Greg Tankard +// nsw.gov.au Bug 547985 - Removed at request of +// nt.gov.au Bug 940478 - Removed at request of Greg Connors +qld.gov.au +sa.gov.au +tas.gov.au +vic.gov.au +wa.gov.au + +// aw : https://en.wikipedia.org/wiki/.aw +aw +com.aw + +// ax : https://en.wikipedia.org/wiki/.ax +ax + +// az : https://en.wikipedia.org/wiki/.az +az +com.az +net.az +int.az +gov.az +org.az +edu.az +info.az +pp.az +mil.az +name.az +pro.az +biz.az + +// ba : https://en.wikipedia.org/wiki/.ba +ba +org.ba +net.ba +edu.ba +gov.ba +mil.ba +unsa.ba +unbi.ba +co.ba +com.ba +rs.ba + +// bb : https://en.wikipedia.org/wiki/.bb +bb +biz.bb +co.bb +com.bb +edu.bb +gov.bb +info.bb +net.bb +org.bb +store.bb +tv.bb + +// bd : https://en.wikipedia.org/wiki/.bd +*.bd + +// be : https://en.wikipedia.org/wiki/.be +// Confirmed by registry 2008-06-08 +be +ac.be + +// bf : https://en.wikipedia.org/wiki/.bf +bf +gov.bf + +// bg : https://en.wikipedia.org/wiki/.bg +// https://www.register.bg/user/static/rules/en/index.html +bg +a.bg +b.bg +c.bg +d.bg +e.bg +f.bg +g.bg +h.bg +i.bg +j.bg +k.bg +l.bg +m.bg +n.bg +o.bg +p.bg +q.bg +r.bg +s.bg +t.bg +u.bg +v.bg +w.bg +x.bg +y.bg +z.bg +0.bg +1.bg +2.bg +3.bg +4.bg +5.bg +6.bg +7.bg +8.bg +9.bg + +// bh : https://en.wikipedia.org/wiki/.bh +bh +com.bh +edu.bh +net.bh +org.bh +gov.bh + +// bi : https://en.wikipedia.org/wiki/.bi +// http://whois.nic.bi/ +bi +co.bi +com.bi +edu.bi +or.bi +org.bi + +// biz : https://en.wikipedia.org/wiki/.biz +biz + +// bj : https://en.wikipedia.org/wiki/.bj +bj +asso.bj +barreau.bj +gouv.bj + +// bm : http://www.bermudanic.bm/dnr-text.txt +bm +com.bm +edu.bm +gov.bm +net.bm +org.bm + +// bn : https://en.wikipedia.org/wiki/.bn +*.bn + +// bo : http://www.nic.bo/ +bo +com.bo +edu.bo +gov.bo +gob.bo +int.bo +org.bo +net.bo +mil.bo +tv.bo + +// br : http://registro.br/dominio/categoria.html +// Submitted by registry +br +adm.br +adv.br +agr.br +am.br +arq.br +art.br +ato.br +b.br +bio.br +blog.br +bmd.br +cim.br +cng.br +cnt.br +com.br +coop.br +ecn.br +eco.br +edu.br +emp.br +eng.br +esp.br +etc.br +eti.br +far.br +flog.br +fm.br +fnd.br +fot.br +fst.br +g12.br +ggf.br +gov.br +imb.br +ind.br +inf.br +jor.br +jus.br +leg.br +lel.br +mat.br +med.br +mil.br +mp.br +mus.br +net.br +*.nom.br +not.br +ntr.br +odo.br +org.br +ppg.br +pro.br +psc.br +psi.br +qsl.br +radio.br +rec.br +slg.br +srv.br +taxi.br +teo.br +tmp.br +trd.br +tur.br +tv.br +vet.br +vlog.br +wiki.br +zlg.br + +// bs : http://www.nic.bs/rules.html +bs +com.bs +net.bs +org.bs +edu.bs +gov.bs + +// bt : https://en.wikipedia.org/wiki/.bt +bt +com.bt +edu.bt +gov.bt +net.bt +org.bt + +// bv : No registrations at this time. +// Submitted by registry +bv + +// bw : https://en.wikipedia.org/wiki/.bw +// http://www.gobin.info/domainname/bw.doc +// list of other 2nd level tlds ? +bw +co.bw +org.bw + +// by : https://en.wikipedia.org/wiki/.by +// http://tld.by/rules_2006_en.html +// list of other 2nd level tlds ? +by +gov.by +mil.by +// Official information does not indicate that com.by is a reserved +// second-level domain, but it's being used as one (see www.google.com.by and +// www.yahoo.com.by, for example), so we list it here for safety's sake. +com.by + +// http://hoster.by/ +of.by + +// bz : https://en.wikipedia.org/wiki/.bz +// http://www.belizenic.bz/ +bz +com.bz +net.bz +org.bz +edu.bz +gov.bz + +// ca : https://en.wikipedia.org/wiki/.ca +ca +// ca geographical names +ab.ca +bc.ca +mb.ca +nb.ca +nf.ca +nl.ca +ns.ca +nt.ca +nu.ca +on.ca +pe.ca +qc.ca +sk.ca +yk.ca +// gc.ca: https://en.wikipedia.org/wiki/.gc.ca +// see also: http://registry.gc.ca/en/SubdomainFAQ +gc.ca + +// cat : https://en.wikipedia.org/wiki/.cat +cat + +// cc : https://en.wikipedia.org/wiki/.cc +cc + +// cd : https://en.wikipedia.org/wiki/.cd +// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 +cd +gov.cd + +// cf : https://en.wikipedia.org/wiki/.cf +cf + +// cg : https://en.wikipedia.org/wiki/.cg +cg + +// ch : https://en.wikipedia.org/wiki/.ch +ch + +// ci : https://en.wikipedia.org/wiki/.ci +// http://www.nic.ci/index.php?page=charte +ci +org.ci +or.ci +com.ci +co.ci +edu.ci +ed.ci +ac.ci +net.ci +go.ci +asso.ci +aéroport.ci +int.ci +presse.ci +md.ci +gouv.ci + +// ck : https://en.wikipedia.org/wiki/.ck +*.ck +!www.ck + +// cl : https://en.wikipedia.org/wiki/.cl +cl +gov.cl +gob.cl +co.cl +mil.cl + +// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 +cm +co.cm +com.cm +gov.cm +net.cm + +// cn : https://en.wikipedia.org/wiki/.cn +// Submitted by registry +cn +ac.cn +com.cn +edu.cn +gov.cn +net.cn +org.cn +mil.cn +公司.cn +网络.cn +網絡.cn +// cn geographic names +ah.cn +bj.cn +cq.cn +fj.cn +gd.cn +gs.cn +gz.cn +gx.cn +ha.cn +hb.cn +he.cn +hi.cn +hl.cn +hn.cn +jl.cn +js.cn +jx.cn +ln.cn +nm.cn +nx.cn +qh.cn +sc.cn +sd.cn +sh.cn +sn.cn +sx.cn +tj.cn +xj.cn +xz.cn +yn.cn +zj.cn +hk.cn +mo.cn +tw.cn + +// co : https://en.wikipedia.org/wiki/.co +// Submitted by registry +co +arts.co +com.co +edu.co +firm.co +gov.co +info.co +int.co +mil.co +net.co +nom.co +org.co +rec.co +web.co + +// com : https://en.wikipedia.org/wiki/.com +com + +// coop : https://en.wikipedia.org/wiki/.coop +coop + +// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do +cr +ac.cr +co.cr +ed.cr +fi.cr +go.cr +or.cr +sa.cr + +// cu : https://en.wikipedia.org/wiki/.cu +cu +com.cu +edu.cu +org.cu +net.cu +gov.cu +inf.cu + +// cv : https://en.wikipedia.org/wiki/.cv +cv + +// cw : http://www.una.cw/cw_registry/ +// Confirmed by registry 2013-03-26 +cw +com.cw +edu.cw +net.cw +org.cw + +// cx : https://en.wikipedia.org/wiki/.cx +// list of other 2nd level tlds ? +cx +gov.cx + +// cy : https://en.wikipedia.org/wiki/.cy +ac.cy +biz.cy +com.cy +ekloges.cy +gov.cy +ltd.cy +name.cy +net.cy +org.cy +parliament.cy +press.cy +pro.cy +tm.cy + +// cz : https://en.wikipedia.org/wiki/.cz +cz + +// de : https://en.wikipedia.org/wiki/.de +// Confirmed by registry (with technical +// reservations) 2008-07-01 +de + +// dj : https://en.wikipedia.org/wiki/.dj +dj + +// dk : https://en.wikipedia.org/wiki/.dk +// Confirmed by registry 2008-06-17 +dk + +// dm : https://en.wikipedia.org/wiki/.dm +dm +com.dm +net.dm +org.dm +edu.dm +gov.dm + +// do : https://en.wikipedia.org/wiki/.do +do +art.do +com.do +edu.do +gob.do +gov.do +mil.do +net.do +org.do +sld.do +web.do + +// dz : https://en.wikipedia.org/wiki/.dz +dz +com.dz +org.dz +net.dz +gov.dz +edu.dz +asso.dz +pol.dz +art.dz + +// ec : http://www.nic.ec/reg/paso1.asp +// Submitted by registry +ec +com.ec +info.ec +net.ec +fin.ec +k12.ec +med.ec +pro.ec +org.ec +edu.ec +gov.ec +gob.ec +mil.ec + +// edu : https://en.wikipedia.org/wiki/.edu +edu + +// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B +ee +edu.ee +gov.ee +riik.ee +lib.ee +med.ee +com.ee +pri.ee +aip.ee +org.ee +fie.ee + +// eg : https://en.wikipedia.org/wiki/.eg +eg +com.eg +edu.eg +eun.eg +gov.eg +mil.eg +name.eg +net.eg +org.eg +sci.eg + +// er : https://en.wikipedia.org/wiki/.er +*.er + +// es : https://www.nic.es/site_ingles/ingles/dominios/index.html +es +com.es +nom.es +org.es +gob.es +edu.es + +// et : https://en.wikipedia.org/wiki/.et +et +com.et +gov.et +org.et +edu.et +biz.et +name.et +info.et +net.et + +// eu : https://en.wikipedia.org/wiki/.eu +eu + +// fi : https://en.wikipedia.org/wiki/.fi +fi +// aland.fi : https://en.wikipedia.org/wiki/.ax +// This domain is being phased out in favor of .ax. As there are still many +// domains under aland.fi, we still keep it on the list until aland.fi is +// completely removed. +// TODO: Check for updates (expected to be phased out around Q1/2009) +aland.fi + +// fj : https://en.wikipedia.org/wiki/.fj +*.fj + +// fk : https://en.wikipedia.org/wiki/.fk +*.fk + +// fm : https://en.wikipedia.org/wiki/.fm +fm + +// fo : https://en.wikipedia.org/wiki/.fo +fo + +// fr : http://www.afnic.fr/ +// domaines descriptifs : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-descriptifs +fr +com.fr +asso.fr +nom.fr +prd.fr +presse.fr +tm.fr +// domaines sectoriels : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-sectoriels +aeroport.fr +assedic.fr +avocat.fr +avoues.fr +cci.fr +chambagri.fr +chirurgiens-dentistes.fr +experts-comptables.fr +geometre-expert.fr +gouv.fr +greta.fr +huissier-justice.fr +medecin.fr +notaires.fr +pharmacien.fr +port.fr +veterinaire.fr + +// ga : https://en.wikipedia.org/wiki/.ga +ga + +// gb : This registry is effectively dormant +// Submitted by registry +gb + +// gd : https://en.wikipedia.org/wiki/.gd +gd + +// ge : http://www.nic.net.ge/policy_en.pdf +ge +com.ge +edu.ge +gov.ge +org.ge +mil.ge +net.ge +pvt.ge + +// gf : https://en.wikipedia.org/wiki/.gf +gf + +// gg : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +gg +co.gg +net.gg +org.gg + +// gh : https://en.wikipedia.org/wiki/.gh +// see also: http://www.nic.gh/reg_now.php +// Although domains directly at second level are not possible at the moment, +// they have been possible for some time and may come back. +gh +com.gh +edu.gh +gov.gh +org.gh +mil.gh + +// gi : http://www.nic.gi/rules.html +gi +com.gi +ltd.gi +gov.gi +mod.gi +edu.gi +org.gi + +// gl : https://en.wikipedia.org/wiki/.gl +// http://nic.gl +gl +co.gl +com.gl +edu.gl +net.gl +org.gl + +// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm +gm + +// gn : http://psg.com/dns/gn/gn.txt +// Submitted by registry +gn +ac.gn +com.gn +edu.gn +gov.gn +org.gn +net.gn + +// gov : https://en.wikipedia.org/wiki/.gov +gov + +// gp : http://www.nic.gp/index.php?lang=en +gp +com.gp +net.gp +mobi.gp +edu.gp +org.gp +asso.gp + +// gq : https://en.wikipedia.org/wiki/.gq +gq + +// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html +// Submitted by registry +gr +com.gr +edu.gr +net.gr +org.gr +gov.gr + +// gs : https://en.wikipedia.org/wiki/.gs +gs + +// gt : http://www.gt/politicas_de_registro.html +gt +com.gt +edu.gt +gob.gt +ind.gt +mil.gt +net.gt +org.gt + +// gu : http://gadao.gov.gu/registration.txt +*.gu + +// gw : https://en.wikipedia.org/wiki/.gw +gw + +// gy : https://en.wikipedia.org/wiki/.gy +// http://registry.gy/ +gy +co.gy +com.gy +edu.gy +gov.gy +net.gy +org.gy + +// hk : https://www.hkdnr.hk +// Submitted by registry +hk +com.hk +edu.hk +gov.hk +idv.hk +net.hk +org.hk +公司.hk +教育.hk +敎育.hk +政府.hk +個人.hk +个人.hk +箇人.hk +網络.hk +网络.hk +组織.hk +網絡.hk +网絡.hk +组织.hk +組織.hk +組织.hk + +// hm : https://en.wikipedia.org/wiki/.hm +hm + +// hn : http://www.nic.hn/politicas/ps02,,05.html +hn +com.hn +edu.hn +org.hn +net.hn +mil.hn +gob.hn + +// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf +hr +iz.hr +from.hr +name.hr +com.hr + +// ht : http://www.nic.ht/info/charte.cfm +ht +com.ht +shop.ht +firm.ht +info.ht +adult.ht +net.ht +pro.ht +org.ht +med.ht +art.ht +coop.ht +pol.ht +asso.ht +edu.ht +rel.ht +gouv.ht +perso.ht + +// hu : http://www.domain.hu/domain/English/sld.html +// Confirmed by registry 2008-06-12 +hu +co.hu +info.hu +org.hu +priv.hu +sport.hu +tm.hu +2000.hu +agrar.hu +bolt.hu +casino.hu +city.hu +erotica.hu +erotika.hu +film.hu +forum.hu +games.hu +hotel.hu +ingatlan.hu +jogasz.hu +konyvelo.hu +lakas.hu +media.hu +news.hu +reklam.hu +sex.hu +shop.hu +suli.hu +szex.hu +tozsde.hu +utazas.hu +video.hu + +// id : https://register.pandi.or.id/ +id +ac.id +biz.id +co.id +desa.id +go.id +mil.id +my.id +net.id +or.id +sch.id +web.id + +// ie : https://en.wikipedia.org/wiki/.ie +ie +gov.ie + +// il : http://www.isoc.org.il/domains/ +il +ac.il +co.il +gov.il +idf.il +k12.il +muni.il +net.il +org.il + +// im : https://www.nic.im/ +// Submitted by registry +im +ac.im +co.im +com.im +ltd.co.im +net.im +org.im +plc.co.im +tt.im +tv.im + +// in : https://en.wikipedia.org/wiki/.in +// see also: https://registry.in/Policies +// Please note, that nic.in is not an official eTLD, but used by most +// government institutions. +in +co.in +firm.in +net.in +org.in +gen.in +ind.in +nic.in +ac.in +edu.in +res.in +gov.in +mil.in + +// info : https://en.wikipedia.org/wiki/.info +info + +// int : https://en.wikipedia.org/wiki/.int +// Confirmed by registry 2008-06-18 +int +eu.int + +// io : http://www.nic.io/rules.html +// list of other 2nd level tlds ? +io +com.io + +// iq : http://www.cmc.iq/english/iq/iqregister1.htm +iq +gov.iq +edu.iq +mil.iq +com.iq +org.iq +net.iq + +// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules +// Also see http://www.nic.ir/Internationalized_Domain_Names +// Two .ir entries added at request of , 2010-04-16 +ir +ac.ir +co.ir +gov.ir +id.ir +net.ir +org.ir +sch.ir +// xn--mgba3a4f16a.ir (.ir, Persian YEH) +ایران.ir +// xn--mgba3a4fra.ir (.ir, Arabic YEH) +ايران.ir + +// is : http://www.isnic.is/domain/rules.php +// Confirmed by registry 2008-12-06 +is +net.is +com.is +edu.is +gov.is +org.is +int.is + +// it : https://en.wikipedia.org/wiki/.it +it +gov.it +edu.it +// Reserved geo-names: +// http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf +// There is also a list of reserved geo-names corresponding to Italian municipalities +// http://www.nic.it/documenti/appendice-c.pdf, but it is not included here. +// Regions +abr.it +abruzzo.it +aosta-valley.it +aostavalley.it +bas.it +basilicata.it +cal.it +calabria.it +cam.it +campania.it +emilia-romagna.it +emiliaromagna.it +emr.it +friuli-v-giulia.it +friuli-ve-giulia.it +friuli-vegiulia.it +friuli-venezia-giulia.it +friuli-veneziagiulia.it +friuli-vgiulia.it +friuliv-giulia.it +friulive-giulia.it +friulivegiulia.it +friulivenezia-giulia.it +friuliveneziagiulia.it +friulivgiulia.it +fvg.it +laz.it +lazio.it +lig.it +liguria.it +lom.it +lombardia.it +lombardy.it +lucania.it +mar.it +marche.it +mol.it +molise.it +piedmont.it +piemonte.it +pmn.it +pug.it +puglia.it +sar.it +sardegna.it +sardinia.it +sic.it +sicilia.it +sicily.it +taa.it +tos.it +toscana.it +trentino-a-adige.it +trentino-aadige.it +trentino-alto-adige.it +trentino-altoadige.it +trentino-s-tirol.it +trentino-stirol.it +trentino-sud-tirol.it +trentino-sudtirol.it +trentino-sued-tirol.it +trentino-suedtirol.it +trentinoa-adige.it +trentinoaadige.it +trentinoalto-adige.it +trentinoaltoadige.it +trentinos-tirol.it +trentinostirol.it +trentinosud-tirol.it +trentinosudtirol.it +trentinosued-tirol.it +trentinosuedtirol.it +tuscany.it +umb.it +umbria.it +val-d-aosta.it +val-daosta.it +vald-aosta.it +valdaosta.it +valle-aosta.it +valle-d-aosta.it +valle-daosta.it +valleaosta.it +valled-aosta.it +valledaosta.it +vallee-aoste.it +valleeaoste.it +vao.it +vda.it +ven.it +veneto.it +// Provinces +ag.it +agrigento.it +al.it +alessandria.it +alto-adige.it +altoadige.it +an.it +ancona.it +andria-barletta-trani.it +andria-trani-barletta.it +andriabarlettatrani.it +andriatranibarletta.it +ao.it +aosta.it +aoste.it +ap.it +aq.it +aquila.it +ar.it +arezzo.it +ascoli-piceno.it +ascolipiceno.it +asti.it +at.it +av.it +avellino.it +ba.it +balsan.it +bari.it +barletta-trani-andria.it +barlettatraniandria.it +belluno.it +benevento.it +bergamo.it +bg.it +bi.it +biella.it +bl.it +bn.it +bo.it +bologna.it +bolzano.it +bozen.it +br.it +brescia.it +brindisi.it +bs.it +bt.it +bz.it +ca.it +cagliari.it +caltanissetta.it +campidano-medio.it +campidanomedio.it +campobasso.it +carbonia-iglesias.it +carboniaiglesias.it +carrara-massa.it +carraramassa.it +caserta.it +catania.it +catanzaro.it +cb.it +ce.it +cesena-forli.it +cesenaforli.it +ch.it +chieti.it +ci.it +cl.it +cn.it +co.it +como.it +cosenza.it +cr.it +cremona.it +crotone.it +cs.it +ct.it +cuneo.it +cz.it +dell-ogliastra.it +dellogliastra.it +en.it +enna.it +fc.it +fe.it +fermo.it +ferrara.it +fg.it +fi.it +firenze.it +florence.it +fm.it +foggia.it +forli-cesena.it +forlicesena.it +fr.it +frosinone.it +ge.it +genoa.it +genova.it +go.it +gorizia.it +gr.it +grosseto.it +iglesias-carbonia.it +iglesiascarbonia.it +im.it +imperia.it +is.it +isernia.it +kr.it +la-spezia.it +laquila.it +laspezia.it +latina.it +lc.it +le.it +lecce.it +lecco.it +li.it +livorno.it +lo.it +lodi.it +lt.it +lu.it +lucca.it +macerata.it +mantova.it +massa-carrara.it +massacarrara.it +matera.it +mb.it +mc.it +me.it +medio-campidano.it +mediocampidano.it +messina.it +mi.it +milan.it +milano.it +mn.it +mo.it +modena.it +monza-brianza.it +monza-e-della-brianza.it +monza.it +monzabrianza.it +monzaebrianza.it +monzaedellabrianza.it +ms.it +mt.it +na.it +naples.it +napoli.it +no.it +novara.it +nu.it +nuoro.it +og.it +ogliastra.it +olbia-tempio.it +olbiatempio.it +or.it +oristano.it +ot.it +pa.it +padova.it +padua.it +palermo.it +parma.it +pavia.it +pc.it +pd.it +pe.it +perugia.it +pesaro-urbino.it +pesarourbino.it +pescara.it +pg.it +pi.it +piacenza.it +pisa.it +pistoia.it +pn.it +po.it +pordenone.it +potenza.it +pr.it +prato.it +pt.it +pu.it +pv.it +pz.it +ra.it +ragusa.it +ravenna.it +rc.it +re.it +reggio-calabria.it +reggio-emilia.it +reggiocalabria.it +reggioemilia.it +rg.it +ri.it +rieti.it +rimini.it +rm.it +rn.it +ro.it +roma.it +rome.it +rovigo.it +sa.it +salerno.it +sassari.it +savona.it +si.it +siena.it +siracusa.it +so.it +sondrio.it +sp.it +sr.it +ss.it +suedtirol.it +sv.it +ta.it +taranto.it +te.it +tempio-olbia.it +tempioolbia.it +teramo.it +terni.it +tn.it +to.it +torino.it +tp.it +tr.it +trani-andria-barletta.it +trani-barletta-andria.it +traniandriabarletta.it +tranibarlettaandria.it +trapani.it +trentino.it +trento.it +treviso.it +trieste.it +ts.it +turin.it +tv.it +ud.it +udine.it +urbino-pesaro.it +urbinopesaro.it +va.it +varese.it +vb.it +vc.it +ve.it +venezia.it +venice.it +verbania.it +vercelli.it +verona.it +vi.it +vibo-valentia.it +vibovalentia.it +vicenza.it +viterbo.it +vr.it +vs.it +vt.it +vv.it + +// je : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +je +co.je +net.je +org.je + +// jm : http://www.com.jm/register.html +*.jm + +// jo : http://www.dns.jo/Registration_policy.aspx +jo +com.jo +org.jo +net.jo +edu.jo +sch.jo +gov.jo +mil.jo +name.jo + +// jobs : https://en.wikipedia.org/wiki/.jobs +jobs + +// jp : https://en.wikipedia.org/wiki/.jp +// http://jprs.co.jp/en/jpdomain.html +// Submitted by registry +jp +// jp organizational type names +ac.jp +ad.jp +co.jp +ed.jp +go.jp +gr.jp +lg.jp +ne.jp +or.jp +// jp prefecture type names +aichi.jp +akita.jp +aomori.jp +chiba.jp +ehime.jp +fukui.jp +fukuoka.jp +fukushima.jp +gifu.jp +gunma.jp +hiroshima.jp +hokkaido.jp +hyogo.jp +ibaraki.jp +ishikawa.jp +iwate.jp +kagawa.jp +kagoshima.jp +kanagawa.jp +kochi.jp +kumamoto.jp +kyoto.jp +mie.jp +miyagi.jp +miyazaki.jp +nagano.jp +nagasaki.jp +nara.jp +niigata.jp +oita.jp +okayama.jp +okinawa.jp +osaka.jp +saga.jp +saitama.jp +shiga.jp +shimane.jp +shizuoka.jp +tochigi.jp +tokushima.jp +tokyo.jp +tottori.jp +toyama.jp +wakayama.jp +yamagata.jp +yamaguchi.jp +yamanashi.jp +栃木.jp +愛知.jp +愛媛.jp +兵庫.jp +熊本.jp +茨城.jp +北海道.jp +千葉.jp +和歌山.jp +長崎.jp +長野.jp +新潟.jp +青森.jp +静岡.jp +東京.jp +石川.jp +埼玉.jp +三重.jp +京都.jp +佐賀.jp +大分.jp +大阪.jp +奈良.jp +宮城.jp +宮崎.jp +富山.jp +山口.jp +山形.jp +山梨.jp +岩手.jp +岐阜.jp +岡山.jp +島根.jp +広島.jp +徳島.jp +沖縄.jp +滋賀.jp +神奈川.jp +福井.jp +福岡.jp +福島.jp +秋田.jp +群馬.jp +香川.jp +高知.jp +鳥取.jp +鹿児島.jp +// jp geographic type names +// http://jprs.jp/doc/rule/saisoku-1.html +*.kawasaki.jp +*.kitakyushu.jp +*.kobe.jp +*.nagoya.jp +*.sapporo.jp +*.sendai.jp +*.yokohama.jp +!city.kawasaki.jp +!city.kitakyushu.jp +!city.kobe.jp +!city.nagoya.jp +!city.sapporo.jp +!city.sendai.jp +!city.yokohama.jp +// 4th level registration +aisai.aichi.jp +ama.aichi.jp +anjo.aichi.jp +asuke.aichi.jp +chiryu.aichi.jp +chita.aichi.jp +fuso.aichi.jp +gamagori.aichi.jp +handa.aichi.jp +hazu.aichi.jp +hekinan.aichi.jp +higashiura.aichi.jp +ichinomiya.aichi.jp +inazawa.aichi.jp +inuyama.aichi.jp +isshiki.aichi.jp +iwakura.aichi.jp +kanie.aichi.jp +kariya.aichi.jp +kasugai.aichi.jp +kira.aichi.jp +kiyosu.aichi.jp +komaki.aichi.jp +konan.aichi.jp +kota.aichi.jp +mihama.aichi.jp +miyoshi.aichi.jp +nishio.aichi.jp +nisshin.aichi.jp +obu.aichi.jp +oguchi.aichi.jp +oharu.aichi.jp +okazaki.aichi.jp +owariasahi.aichi.jp +seto.aichi.jp +shikatsu.aichi.jp +shinshiro.aichi.jp +shitara.aichi.jp +tahara.aichi.jp +takahama.aichi.jp +tobishima.aichi.jp +toei.aichi.jp +togo.aichi.jp +tokai.aichi.jp +tokoname.aichi.jp +toyoake.aichi.jp +toyohashi.aichi.jp +toyokawa.aichi.jp +toyone.aichi.jp +toyota.aichi.jp +tsushima.aichi.jp +yatomi.aichi.jp +akita.akita.jp +daisen.akita.jp +fujisato.akita.jp +gojome.akita.jp +hachirogata.akita.jp +happou.akita.jp +higashinaruse.akita.jp +honjo.akita.jp +honjyo.akita.jp +ikawa.akita.jp +kamikoani.akita.jp +kamioka.akita.jp +katagami.akita.jp +kazuno.akita.jp +kitaakita.akita.jp +kosaka.akita.jp +kyowa.akita.jp +misato.akita.jp +mitane.akita.jp +moriyoshi.akita.jp +nikaho.akita.jp +noshiro.akita.jp +odate.akita.jp +oga.akita.jp +ogata.akita.jp +semboku.akita.jp +yokote.akita.jp +yurihonjo.akita.jp +aomori.aomori.jp +gonohe.aomori.jp +hachinohe.aomori.jp +hashikami.aomori.jp +hiranai.aomori.jp +hirosaki.aomori.jp +itayanagi.aomori.jp +kuroishi.aomori.jp +misawa.aomori.jp +mutsu.aomori.jp +nakadomari.aomori.jp +noheji.aomori.jp +oirase.aomori.jp +owani.aomori.jp +rokunohe.aomori.jp +sannohe.aomori.jp +shichinohe.aomori.jp +shingo.aomori.jp +takko.aomori.jp +towada.aomori.jp +tsugaru.aomori.jp +tsuruta.aomori.jp +abiko.chiba.jp +asahi.chiba.jp +chonan.chiba.jp +chosei.chiba.jp +choshi.chiba.jp +chuo.chiba.jp +funabashi.chiba.jp +futtsu.chiba.jp +hanamigawa.chiba.jp +ichihara.chiba.jp +ichikawa.chiba.jp +ichinomiya.chiba.jp +inzai.chiba.jp +isumi.chiba.jp +kamagaya.chiba.jp +kamogawa.chiba.jp +kashiwa.chiba.jp +katori.chiba.jp +katsuura.chiba.jp +kimitsu.chiba.jp +kisarazu.chiba.jp +kozaki.chiba.jp +kujukuri.chiba.jp +kyonan.chiba.jp +matsudo.chiba.jp +midori.chiba.jp +mihama.chiba.jp +minamiboso.chiba.jp +mobara.chiba.jp +mutsuzawa.chiba.jp +nagara.chiba.jp +nagareyama.chiba.jp +narashino.chiba.jp +narita.chiba.jp +noda.chiba.jp +oamishirasato.chiba.jp +omigawa.chiba.jp +onjuku.chiba.jp +otaki.chiba.jp +sakae.chiba.jp +sakura.chiba.jp +shimofusa.chiba.jp +shirako.chiba.jp +shiroi.chiba.jp +shisui.chiba.jp +sodegaura.chiba.jp +sosa.chiba.jp +tako.chiba.jp +tateyama.chiba.jp +togane.chiba.jp +tohnosho.chiba.jp +tomisato.chiba.jp +urayasu.chiba.jp +yachimata.chiba.jp +yachiyo.chiba.jp +yokaichiba.chiba.jp +yokoshibahikari.chiba.jp +yotsukaido.chiba.jp +ainan.ehime.jp +honai.ehime.jp +ikata.ehime.jp +imabari.ehime.jp +iyo.ehime.jp +kamijima.ehime.jp +kihoku.ehime.jp +kumakogen.ehime.jp +masaki.ehime.jp +matsuno.ehime.jp +matsuyama.ehime.jp +namikata.ehime.jp +niihama.ehime.jp +ozu.ehime.jp +saijo.ehime.jp +seiyo.ehime.jp +shikokuchuo.ehime.jp +tobe.ehime.jp +toon.ehime.jp +uchiko.ehime.jp +uwajima.ehime.jp +yawatahama.ehime.jp +echizen.fukui.jp +eiheiji.fukui.jp +fukui.fukui.jp +ikeda.fukui.jp +katsuyama.fukui.jp +mihama.fukui.jp +minamiechizen.fukui.jp +obama.fukui.jp +ohi.fukui.jp +ono.fukui.jp +sabae.fukui.jp +sakai.fukui.jp +takahama.fukui.jp +tsuruga.fukui.jp +wakasa.fukui.jp +ashiya.fukuoka.jp +buzen.fukuoka.jp +chikugo.fukuoka.jp +chikuho.fukuoka.jp +chikujo.fukuoka.jp +chikushino.fukuoka.jp +chikuzen.fukuoka.jp +chuo.fukuoka.jp +dazaifu.fukuoka.jp +fukuchi.fukuoka.jp +hakata.fukuoka.jp +higashi.fukuoka.jp +hirokawa.fukuoka.jp +hisayama.fukuoka.jp +iizuka.fukuoka.jp +inatsuki.fukuoka.jp +kaho.fukuoka.jp +kasuga.fukuoka.jp +kasuya.fukuoka.jp +kawara.fukuoka.jp +keisen.fukuoka.jp +koga.fukuoka.jp +kurate.fukuoka.jp +kurogi.fukuoka.jp +kurume.fukuoka.jp +minami.fukuoka.jp +miyako.fukuoka.jp +miyama.fukuoka.jp +miyawaka.fukuoka.jp +mizumaki.fukuoka.jp +munakata.fukuoka.jp +nakagawa.fukuoka.jp +nakama.fukuoka.jp +nishi.fukuoka.jp +nogata.fukuoka.jp +ogori.fukuoka.jp +okagaki.fukuoka.jp +okawa.fukuoka.jp +oki.fukuoka.jp +omuta.fukuoka.jp +onga.fukuoka.jp +onojo.fukuoka.jp +oto.fukuoka.jp +saigawa.fukuoka.jp +sasaguri.fukuoka.jp +shingu.fukuoka.jp +shinyoshitomi.fukuoka.jp +shonai.fukuoka.jp +soeda.fukuoka.jp +sue.fukuoka.jp +tachiarai.fukuoka.jp +tagawa.fukuoka.jp +takata.fukuoka.jp +toho.fukuoka.jp +toyotsu.fukuoka.jp +tsuiki.fukuoka.jp +ukiha.fukuoka.jp +umi.fukuoka.jp +usui.fukuoka.jp +yamada.fukuoka.jp +yame.fukuoka.jp +yanagawa.fukuoka.jp +yukuhashi.fukuoka.jp +aizubange.fukushima.jp +aizumisato.fukushima.jp +aizuwakamatsu.fukushima.jp +asakawa.fukushima.jp +bandai.fukushima.jp +date.fukushima.jp +fukushima.fukushima.jp +furudono.fukushima.jp +futaba.fukushima.jp +hanawa.fukushima.jp +higashi.fukushima.jp +hirata.fukushima.jp +hirono.fukushima.jp +iitate.fukushima.jp +inawashiro.fukushima.jp +ishikawa.fukushima.jp +iwaki.fukushima.jp +izumizaki.fukushima.jp +kagamiishi.fukushima.jp +kaneyama.fukushima.jp +kawamata.fukushima.jp +kitakata.fukushima.jp +kitashiobara.fukushima.jp +koori.fukushima.jp +koriyama.fukushima.jp +kunimi.fukushima.jp +miharu.fukushima.jp +mishima.fukushima.jp +namie.fukushima.jp +nango.fukushima.jp +nishiaizu.fukushima.jp +nishigo.fukushima.jp +okuma.fukushima.jp +omotego.fukushima.jp +ono.fukushima.jp +otama.fukushima.jp +samegawa.fukushima.jp +shimogo.fukushima.jp +shirakawa.fukushima.jp +showa.fukushima.jp +soma.fukushima.jp +sukagawa.fukushima.jp +taishin.fukushima.jp +tamakawa.fukushima.jp +tanagura.fukushima.jp +tenei.fukushima.jp +yabuki.fukushima.jp +yamato.fukushima.jp +yamatsuri.fukushima.jp +yanaizu.fukushima.jp +yugawa.fukushima.jp +anpachi.gifu.jp +ena.gifu.jp +gifu.gifu.jp +ginan.gifu.jp +godo.gifu.jp +gujo.gifu.jp +hashima.gifu.jp +hichiso.gifu.jp +hida.gifu.jp +higashishirakawa.gifu.jp +ibigawa.gifu.jp +ikeda.gifu.jp +kakamigahara.gifu.jp +kani.gifu.jp +kasahara.gifu.jp +kasamatsu.gifu.jp +kawaue.gifu.jp +kitagata.gifu.jp +mino.gifu.jp +minokamo.gifu.jp +mitake.gifu.jp +mizunami.gifu.jp +motosu.gifu.jp +nakatsugawa.gifu.jp +ogaki.gifu.jp +sakahogi.gifu.jp +seki.gifu.jp +sekigahara.gifu.jp +shirakawa.gifu.jp +tajimi.gifu.jp +takayama.gifu.jp +tarui.gifu.jp +toki.gifu.jp +tomika.gifu.jp +wanouchi.gifu.jp +yamagata.gifu.jp +yaotsu.gifu.jp +yoro.gifu.jp +annaka.gunma.jp +chiyoda.gunma.jp +fujioka.gunma.jp +higashiagatsuma.gunma.jp +isesaki.gunma.jp +itakura.gunma.jp +kanna.gunma.jp +kanra.gunma.jp +katashina.gunma.jp +kawaba.gunma.jp +kiryu.gunma.jp +kusatsu.gunma.jp +maebashi.gunma.jp +meiwa.gunma.jp +midori.gunma.jp +minakami.gunma.jp +naganohara.gunma.jp +nakanojo.gunma.jp +nanmoku.gunma.jp +numata.gunma.jp +oizumi.gunma.jp +ora.gunma.jp +ota.gunma.jp +shibukawa.gunma.jp +shimonita.gunma.jp +shinto.gunma.jp +showa.gunma.jp +takasaki.gunma.jp +takayama.gunma.jp +tamamura.gunma.jp +tatebayashi.gunma.jp +tomioka.gunma.jp +tsukiyono.gunma.jp +tsumagoi.gunma.jp +ueno.gunma.jp +yoshioka.gunma.jp +asaminami.hiroshima.jp +daiwa.hiroshima.jp +etajima.hiroshima.jp +fuchu.hiroshima.jp +fukuyama.hiroshima.jp +hatsukaichi.hiroshima.jp +higashihiroshima.hiroshima.jp +hongo.hiroshima.jp +jinsekikogen.hiroshima.jp +kaita.hiroshima.jp +kui.hiroshima.jp +kumano.hiroshima.jp +kure.hiroshima.jp +mihara.hiroshima.jp +miyoshi.hiroshima.jp +naka.hiroshima.jp +onomichi.hiroshima.jp +osakikamijima.hiroshima.jp +otake.hiroshima.jp +saka.hiroshima.jp +sera.hiroshima.jp +seranishi.hiroshima.jp +shinichi.hiroshima.jp +shobara.hiroshima.jp +takehara.hiroshima.jp +abashiri.hokkaido.jp +abira.hokkaido.jp +aibetsu.hokkaido.jp +akabira.hokkaido.jp +akkeshi.hokkaido.jp +asahikawa.hokkaido.jp +ashibetsu.hokkaido.jp +ashoro.hokkaido.jp +assabu.hokkaido.jp +atsuma.hokkaido.jp +bibai.hokkaido.jp +biei.hokkaido.jp +bifuka.hokkaido.jp +bihoro.hokkaido.jp +biratori.hokkaido.jp +chippubetsu.hokkaido.jp +chitose.hokkaido.jp +date.hokkaido.jp +ebetsu.hokkaido.jp +embetsu.hokkaido.jp +eniwa.hokkaido.jp +erimo.hokkaido.jp +esan.hokkaido.jp +esashi.hokkaido.jp +fukagawa.hokkaido.jp +fukushima.hokkaido.jp +furano.hokkaido.jp +furubira.hokkaido.jp +haboro.hokkaido.jp +hakodate.hokkaido.jp +hamatonbetsu.hokkaido.jp +hidaka.hokkaido.jp +higashikagura.hokkaido.jp +higashikawa.hokkaido.jp +hiroo.hokkaido.jp +hokuryu.hokkaido.jp +hokuto.hokkaido.jp +honbetsu.hokkaido.jp +horokanai.hokkaido.jp +horonobe.hokkaido.jp +ikeda.hokkaido.jp +imakane.hokkaido.jp +ishikari.hokkaido.jp +iwamizawa.hokkaido.jp +iwanai.hokkaido.jp +kamifurano.hokkaido.jp +kamikawa.hokkaido.jp +kamishihoro.hokkaido.jp +kamisunagawa.hokkaido.jp +kamoenai.hokkaido.jp +kayabe.hokkaido.jp +kembuchi.hokkaido.jp +kikonai.hokkaido.jp +kimobetsu.hokkaido.jp +kitahiroshima.hokkaido.jp +kitami.hokkaido.jp +kiyosato.hokkaido.jp +koshimizu.hokkaido.jp +kunneppu.hokkaido.jp +kuriyama.hokkaido.jp +kuromatsunai.hokkaido.jp +kushiro.hokkaido.jp +kutchan.hokkaido.jp +kyowa.hokkaido.jp +mashike.hokkaido.jp +matsumae.hokkaido.jp +mikasa.hokkaido.jp +minamifurano.hokkaido.jp +mombetsu.hokkaido.jp +moseushi.hokkaido.jp +mukawa.hokkaido.jp +muroran.hokkaido.jp +naie.hokkaido.jp +nakagawa.hokkaido.jp +nakasatsunai.hokkaido.jp +nakatombetsu.hokkaido.jp +nanae.hokkaido.jp +nanporo.hokkaido.jp +nayoro.hokkaido.jp +nemuro.hokkaido.jp +niikappu.hokkaido.jp +niki.hokkaido.jp +nishiokoppe.hokkaido.jp +noboribetsu.hokkaido.jp +numata.hokkaido.jp +obihiro.hokkaido.jp +obira.hokkaido.jp +oketo.hokkaido.jp +okoppe.hokkaido.jp +otaru.hokkaido.jp +otobe.hokkaido.jp +otofuke.hokkaido.jp +otoineppu.hokkaido.jp +oumu.hokkaido.jp +ozora.hokkaido.jp +pippu.hokkaido.jp +rankoshi.hokkaido.jp +rebun.hokkaido.jp +rikubetsu.hokkaido.jp +rishiri.hokkaido.jp +rishirifuji.hokkaido.jp +saroma.hokkaido.jp +sarufutsu.hokkaido.jp +shakotan.hokkaido.jp +shari.hokkaido.jp +shibecha.hokkaido.jp +shibetsu.hokkaido.jp +shikabe.hokkaido.jp +shikaoi.hokkaido.jp +shimamaki.hokkaido.jp +shimizu.hokkaido.jp +shimokawa.hokkaido.jp +shinshinotsu.hokkaido.jp +shintoku.hokkaido.jp +shiranuka.hokkaido.jp +shiraoi.hokkaido.jp +shiriuchi.hokkaido.jp +sobetsu.hokkaido.jp +sunagawa.hokkaido.jp +taiki.hokkaido.jp +takasu.hokkaido.jp +takikawa.hokkaido.jp +takinoue.hokkaido.jp +teshikaga.hokkaido.jp +tobetsu.hokkaido.jp +tohma.hokkaido.jp +tomakomai.hokkaido.jp +tomari.hokkaido.jp +toya.hokkaido.jp +toyako.hokkaido.jp +toyotomi.hokkaido.jp +toyoura.hokkaido.jp +tsubetsu.hokkaido.jp +tsukigata.hokkaido.jp +urakawa.hokkaido.jp +urausu.hokkaido.jp +uryu.hokkaido.jp +utashinai.hokkaido.jp +wakkanai.hokkaido.jp +wassamu.hokkaido.jp +yakumo.hokkaido.jp +yoichi.hokkaido.jp +aioi.hyogo.jp +akashi.hyogo.jp +ako.hyogo.jp +amagasaki.hyogo.jp +aogaki.hyogo.jp +asago.hyogo.jp +ashiya.hyogo.jp +awaji.hyogo.jp +fukusaki.hyogo.jp +goshiki.hyogo.jp +harima.hyogo.jp +himeji.hyogo.jp +ichikawa.hyogo.jp +inagawa.hyogo.jp +itami.hyogo.jp +kakogawa.hyogo.jp +kamigori.hyogo.jp +kamikawa.hyogo.jp +kasai.hyogo.jp +kasuga.hyogo.jp +kawanishi.hyogo.jp +miki.hyogo.jp +minamiawaji.hyogo.jp +nishinomiya.hyogo.jp +nishiwaki.hyogo.jp +ono.hyogo.jp +sanda.hyogo.jp +sannan.hyogo.jp +sasayama.hyogo.jp +sayo.hyogo.jp +shingu.hyogo.jp +shinonsen.hyogo.jp +shiso.hyogo.jp +sumoto.hyogo.jp +taishi.hyogo.jp +taka.hyogo.jp +takarazuka.hyogo.jp +takasago.hyogo.jp +takino.hyogo.jp +tamba.hyogo.jp +tatsuno.hyogo.jp +toyooka.hyogo.jp +yabu.hyogo.jp +yashiro.hyogo.jp +yoka.hyogo.jp +yokawa.hyogo.jp +ami.ibaraki.jp +asahi.ibaraki.jp +bando.ibaraki.jp +chikusei.ibaraki.jp +daigo.ibaraki.jp +fujishiro.ibaraki.jp +hitachi.ibaraki.jp +hitachinaka.ibaraki.jp +hitachiomiya.ibaraki.jp +hitachiota.ibaraki.jp +ibaraki.ibaraki.jp +ina.ibaraki.jp +inashiki.ibaraki.jp +itako.ibaraki.jp +iwama.ibaraki.jp +joso.ibaraki.jp +kamisu.ibaraki.jp +kasama.ibaraki.jp +kashima.ibaraki.jp +kasumigaura.ibaraki.jp +koga.ibaraki.jp +miho.ibaraki.jp +mito.ibaraki.jp +moriya.ibaraki.jp +naka.ibaraki.jp +namegata.ibaraki.jp +oarai.ibaraki.jp +ogawa.ibaraki.jp +omitama.ibaraki.jp +ryugasaki.ibaraki.jp +sakai.ibaraki.jp +sakuragawa.ibaraki.jp +shimodate.ibaraki.jp +shimotsuma.ibaraki.jp +shirosato.ibaraki.jp +sowa.ibaraki.jp +suifu.ibaraki.jp +takahagi.ibaraki.jp +tamatsukuri.ibaraki.jp +tokai.ibaraki.jp +tomobe.ibaraki.jp +tone.ibaraki.jp +toride.ibaraki.jp +tsuchiura.ibaraki.jp +tsukuba.ibaraki.jp +uchihara.ibaraki.jp +ushiku.ibaraki.jp +yachiyo.ibaraki.jp +yamagata.ibaraki.jp +yawara.ibaraki.jp +yuki.ibaraki.jp +anamizu.ishikawa.jp +hakui.ishikawa.jp +hakusan.ishikawa.jp +kaga.ishikawa.jp +kahoku.ishikawa.jp +kanazawa.ishikawa.jp +kawakita.ishikawa.jp +komatsu.ishikawa.jp +nakanoto.ishikawa.jp +nanao.ishikawa.jp +nomi.ishikawa.jp +nonoichi.ishikawa.jp +noto.ishikawa.jp +shika.ishikawa.jp +suzu.ishikawa.jp +tsubata.ishikawa.jp +tsurugi.ishikawa.jp +uchinada.ishikawa.jp +wajima.ishikawa.jp +fudai.iwate.jp +fujisawa.iwate.jp +hanamaki.iwate.jp +hiraizumi.iwate.jp +hirono.iwate.jp +ichinohe.iwate.jp +ichinoseki.iwate.jp +iwaizumi.iwate.jp +iwate.iwate.jp +joboji.iwate.jp +kamaishi.iwate.jp +kanegasaki.iwate.jp +karumai.iwate.jp +kawai.iwate.jp +kitakami.iwate.jp +kuji.iwate.jp +kunohe.iwate.jp +kuzumaki.iwate.jp +miyako.iwate.jp +mizusawa.iwate.jp +morioka.iwate.jp +ninohe.iwate.jp +noda.iwate.jp +ofunato.iwate.jp +oshu.iwate.jp +otsuchi.iwate.jp +rikuzentakata.iwate.jp +shiwa.iwate.jp +shizukuishi.iwate.jp +sumita.iwate.jp +tanohata.iwate.jp +tono.iwate.jp +yahaba.iwate.jp +yamada.iwate.jp +ayagawa.kagawa.jp +higashikagawa.kagawa.jp +kanonji.kagawa.jp +kotohira.kagawa.jp +manno.kagawa.jp +marugame.kagawa.jp +mitoyo.kagawa.jp +naoshima.kagawa.jp +sanuki.kagawa.jp +tadotsu.kagawa.jp +takamatsu.kagawa.jp +tonosho.kagawa.jp +uchinomi.kagawa.jp +utazu.kagawa.jp +zentsuji.kagawa.jp +akune.kagoshima.jp +amami.kagoshima.jp +hioki.kagoshima.jp +isa.kagoshima.jp +isen.kagoshima.jp +izumi.kagoshima.jp +kagoshima.kagoshima.jp +kanoya.kagoshima.jp +kawanabe.kagoshima.jp +kinko.kagoshima.jp +kouyama.kagoshima.jp +makurazaki.kagoshima.jp +matsumoto.kagoshima.jp +minamitane.kagoshima.jp +nakatane.kagoshima.jp +nishinoomote.kagoshima.jp +satsumasendai.kagoshima.jp +soo.kagoshima.jp +tarumizu.kagoshima.jp +yusui.kagoshima.jp +aikawa.kanagawa.jp +atsugi.kanagawa.jp +ayase.kanagawa.jp +chigasaki.kanagawa.jp +ebina.kanagawa.jp +fujisawa.kanagawa.jp +hadano.kanagawa.jp +hakone.kanagawa.jp +hiratsuka.kanagawa.jp +isehara.kanagawa.jp +kaisei.kanagawa.jp +kamakura.kanagawa.jp +kiyokawa.kanagawa.jp +matsuda.kanagawa.jp +minamiashigara.kanagawa.jp +miura.kanagawa.jp +nakai.kanagawa.jp +ninomiya.kanagawa.jp +odawara.kanagawa.jp +oi.kanagawa.jp +oiso.kanagawa.jp +sagamihara.kanagawa.jp +samukawa.kanagawa.jp +tsukui.kanagawa.jp +yamakita.kanagawa.jp +yamato.kanagawa.jp +yokosuka.kanagawa.jp +yugawara.kanagawa.jp +zama.kanagawa.jp +zushi.kanagawa.jp +aki.kochi.jp +geisei.kochi.jp +hidaka.kochi.jp +higashitsuno.kochi.jp +ino.kochi.jp +kagami.kochi.jp +kami.kochi.jp +kitagawa.kochi.jp +kochi.kochi.jp +mihara.kochi.jp +motoyama.kochi.jp +muroto.kochi.jp +nahari.kochi.jp +nakamura.kochi.jp +nankoku.kochi.jp +nishitosa.kochi.jp +niyodogawa.kochi.jp +ochi.kochi.jp +okawa.kochi.jp +otoyo.kochi.jp +otsuki.kochi.jp +sakawa.kochi.jp +sukumo.kochi.jp +susaki.kochi.jp +tosa.kochi.jp +tosashimizu.kochi.jp +toyo.kochi.jp +tsuno.kochi.jp +umaji.kochi.jp +yasuda.kochi.jp +yusuhara.kochi.jp +amakusa.kumamoto.jp +arao.kumamoto.jp +aso.kumamoto.jp +choyo.kumamoto.jp +gyokuto.kumamoto.jp +hitoyoshi.kumamoto.jp +kamiamakusa.kumamoto.jp +kashima.kumamoto.jp +kikuchi.kumamoto.jp +kosa.kumamoto.jp +kumamoto.kumamoto.jp +mashiki.kumamoto.jp +mifune.kumamoto.jp +minamata.kumamoto.jp +minamioguni.kumamoto.jp +nagasu.kumamoto.jp +nishihara.kumamoto.jp +oguni.kumamoto.jp +ozu.kumamoto.jp +sumoto.kumamoto.jp +takamori.kumamoto.jp +uki.kumamoto.jp +uto.kumamoto.jp +yamaga.kumamoto.jp +yamato.kumamoto.jp +yatsushiro.kumamoto.jp +ayabe.kyoto.jp +fukuchiyama.kyoto.jp +higashiyama.kyoto.jp +ide.kyoto.jp +ine.kyoto.jp +joyo.kyoto.jp +kameoka.kyoto.jp +kamo.kyoto.jp +kita.kyoto.jp +kizu.kyoto.jp +kumiyama.kyoto.jp +kyotamba.kyoto.jp +kyotanabe.kyoto.jp +kyotango.kyoto.jp +maizuru.kyoto.jp +minami.kyoto.jp +minamiyamashiro.kyoto.jp +miyazu.kyoto.jp +muko.kyoto.jp +nagaokakyo.kyoto.jp +nakagyo.kyoto.jp +nantan.kyoto.jp +oyamazaki.kyoto.jp +sakyo.kyoto.jp +seika.kyoto.jp +tanabe.kyoto.jp +uji.kyoto.jp +ujitawara.kyoto.jp +wazuka.kyoto.jp +yamashina.kyoto.jp +yawata.kyoto.jp +asahi.mie.jp +inabe.mie.jp +ise.mie.jp +kameyama.mie.jp +kawagoe.mie.jp +kiho.mie.jp +kisosaki.mie.jp +kiwa.mie.jp +komono.mie.jp +kumano.mie.jp +kuwana.mie.jp +matsusaka.mie.jp +meiwa.mie.jp +mihama.mie.jp +minamiise.mie.jp +misugi.mie.jp +miyama.mie.jp +nabari.mie.jp +shima.mie.jp +suzuka.mie.jp +tado.mie.jp +taiki.mie.jp +taki.mie.jp +tamaki.mie.jp +toba.mie.jp +tsu.mie.jp +udono.mie.jp +ureshino.mie.jp +watarai.mie.jp +yokkaichi.mie.jp +furukawa.miyagi.jp +higashimatsushima.miyagi.jp +ishinomaki.miyagi.jp +iwanuma.miyagi.jp +kakuda.miyagi.jp +kami.miyagi.jp +kawasaki.miyagi.jp +marumori.miyagi.jp +matsushima.miyagi.jp +minamisanriku.miyagi.jp +misato.miyagi.jp +murata.miyagi.jp +natori.miyagi.jp +ogawara.miyagi.jp +ohira.miyagi.jp +onagawa.miyagi.jp +osaki.miyagi.jp +rifu.miyagi.jp +semine.miyagi.jp +shibata.miyagi.jp +shichikashuku.miyagi.jp +shikama.miyagi.jp +shiogama.miyagi.jp +shiroishi.miyagi.jp +tagajo.miyagi.jp +taiwa.miyagi.jp +tome.miyagi.jp +tomiya.miyagi.jp +wakuya.miyagi.jp +watari.miyagi.jp +yamamoto.miyagi.jp +zao.miyagi.jp +aya.miyazaki.jp +ebino.miyazaki.jp +gokase.miyazaki.jp +hyuga.miyazaki.jp +kadogawa.miyazaki.jp +kawaminami.miyazaki.jp +kijo.miyazaki.jp +kitagawa.miyazaki.jp +kitakata.miyazaki.jp +kitaura.miyazaki.jp +kobayashi.miyazaki.jp +kunitomi.miyazaki.jp +kushima.miyazaki.jp +mimata.miyazaki.jp +miyakonojo.miyazaki.jp +miyazaki.miyazaki.jp +morotsuka.miyazaki.jp +nichinan.miyazaki.jp +nishimera.miyazaki.jp +nobeoka.miyazaki.jp +saito.miyazaki.jp +shiiba.miyazaki.jp +shintomi.miyazaki.jp +takaharu.miyazaki.jp +takanabe.miyazaki.jp +takazaki.miyazaki.jp +tsuno.miyazaki.jp +achi.nagano.jp +agematsu.nagano.jp +anan.nagano.jp +aoki.nagano.jp +asahi.nagano.jp +azumino.nagano.jp +chikuhoku.nagano.jp +chikuma.nagano.jp +chino.nagano.jp +fujimi.nagano.jp +hakuba.nagano.jp +hara.nagano.jp +hiraya.nagano.jp +iida.nagano.jp +iijima.nagano.jp +iiyama.nagano.jp +iizuna.nagano.jp +ikeda.nagano.jp +ikusaka.nagano.jp +ina.nagano.jp +karuizawa.nagano.jp +kawakami.nagano.jp +kiso.nagano.jp +kisofukushima.nagano.jp +kitaaiki.nagano.jp +komagane.nagano.jp +komoro.nagano.jp +matsukawa.nagano.jp +matsumoto.nagano.jp +miasa.nagano.jp +minamiaiki.nagano.jp +minamimaki.nagano.jp +minamiminowa.nagano.jp +minowa.nagano.jp +miyada.nagano.jp +miyota.nagano.jp +mochizuki.nagano.jp +nagano.nagano.jp +nagawa.nagano.jp +nagiso.nagano.jp +nakagawa.nagano.jp +nakano.nagano.jp +nozawaonsen.nagano.jp +obuse.nagano.jp +ogawa.nagano.jp +okaya.nagano.jp +omachi.nagano.jp +omi.nagano.jp +ookuwa.nagano.jp +ooshika.nagano.jp +otaki.nagano.jp +otari.nagano.jp +sakae.nagano.jp +sakaki.nagano.jp +saku.nagano.jp +sakuho.nagano.jp +shimosuwa.nagano.jp +shinanomachi.nagano.jp +shiojiri.nagano.jp +suwa.nagano.jp +suzaka.nagano.jp +takagi.nagano.jp +takamori.nagano.jp +takayama.nagano.jp +tateshina.nagano.jp +tatsuno.nagano.jp +togakushi.nagano.jp +togura.nagano.jp +tomi.nagano.jp +ueda.nagano.jp +wada.nagano.jp +yamagata.nagano.jp +yamanouchi.nagano.jp +yasaka.nagano.jp +yasuoka.nagano.jp +chijiwa.nagasaki.jp +futsu.nagasaki.jp +goto.nagasaki.jp +hasami.nagasaki.jp +hirado.nagasaki.jp +iki.nagasaki.jp +isahaya.nagasaki.jp +kawatana.nagasaki.jp +kuchinotsu.nagasaki.jp +matsuura.nagasaki.jp +nagasaki.nagasaki.jp +obama.nagasaki.jp +omura.nagasaki.jp +oseto.nagasaki.jp +saikai.nagasaki.jp +sasebo.nagasaki.jp +seihi.nagasaki.jp +shimabara.nagasaki.jp +shinkamigoto.nagasaki.jp +togitsu.nagasaki.jp +tsushima.nagasaki.jp +unzen.nagasaki.jp +ando.nara.jp +gose.nara.jp +heguri.nara.jp +higashiyoshino.nara.jp +ikaruga.nara.jp +ikoma.nara.jp +kamikitayama.nara.jp +kanmaki.nara.jp +kashiba.nara.jp +kashihara.nara.jp +katsuragi.nara.jp +kawai.nara.jp +kawakami.nara.jp +kawanishi.nara.jp +koryo.nara.jp +kurotaki.nara.jp +mitsue.nara.jp +miyake.nara.jp +nara.nara.jp +nosegawa.nara.jp +oji.nara.jp +ouda.nara.jp +oyodo.nara.jp +sakurai.nara.jp +sango.nara.jp +shimoichi.nara.jp +shimokitayama.nara.jp +shinjo.nara.jp +soni.nara.jp +takatori.nara.jp +tawaramoto.nara.jp +tenkawa.nara.jp +tenri.nara.jp +uda.nara.jp +yamatokoriyama.nara.jp +yamatotakada.nara.jp +yamazoe.nara.jp +yoshino.nara.jp +aga.niigata.jp +agano.niigata.jp +gosen.niigata.jp +itoigawa.niigata.jp +izumozaki.niigata.jp +joetsu.niigata.jp +kamo.niigata.jp +kariwa.niigata.jp +kashiwazaki.niigata.jp +minamiuonuma.niigata.jp +mitsuke.niigata.jp +muika.niigata.jp +murakami.niigata.jp +myoko.niigata.jp +nagaoka.niigata.jp +niigata.niigata.jp +ojiya.niigata.jp +omi.niigata.jp +sado.niigata.jp +sanjo.niigata.jp +seiro.niigata.jp +seirou.niigata.jp +sekikawa.niigata.jp +shibata.niigata.jp +tagami.niigata.jp +tainai.niigata.jp +tochio.niigata.jp +tokamachi.niigata.jp +tsubame.niigata.jp +tsunan.niigata.jp +uonuma.niigata.jp +yahiko.niigata.jp +yoita.niigata.jp +yuzawa.niigata.jp +beppu.oita.jp +bungoono.oita.jp +bungotakada.oita.jp +hasama.oita.jp +hiji.oita.jp +himeshima.oita.jp +hita.oita.jp +kamitsue.oita.jp +kokonoe.oita.jp +kuju.oita.jp +kunisaki.oita.jp +kusu.oita.jp +oita.oita.jp +saiki.oita.jp +taketa.oita.jp +tsukumi.oita.jp +usa.oita.jp +usuki.oita.jp +yufu.oita.jp +akaiwa.okayama.jp +asakuchi.okayama.jp +bizen.okayama.jp +hayashima.okayama.jp +ibara.okayama.jp +kagamino.okayama.jp +kasaoka.okayama.jp +kibichuo.okayama.jp +kumenan.okayama.jp +kurashiki.okayama.jp +maniwa.okayama.jp +misaki.okayama.jp +nagi.okayama.jp +niimi.okayama.jp +nishiawakura.okayama.jp +okayama.okayama.jp +satosho.okayama.jp +setouchi.okayama.jp +shinjo.okayama.jp +shoo.okayama.jp +soja.okayama.jp +takahashi.okayama.jp +tamano.okayama.jp +tsuyama.okayama.jp +wake.okayama.jp +yakage.okayama.jp +aguni.okinawa.jp +ginowan.okinawa.jp +ginoza.okinawa.jp +gushikami.okinawa.jp +haebaru.okinawa.jp +higashi.okinawa.jp +hirara.okinawa.jp +iheya.okinawa.jp +ishigaki.okinawa.jp +ishikawa.okinawa.jp +itoman.okinawa.jp +izena.okinawa.jp +kadena.okinawa.jp +kin.okinawa.jp +kitadaito.okinawa.jp +kitanakagusuku.okinawa.jp +kumejima.okinawa.jp +kunigami.okinawa.jp +minamidaito.okinawa.jp +motobu.okinawa.jp +nago.okinawa.jp +naha.okinawa.jp +nakagusuku.okinawa.jp +nakijin.okinawa.jp +nanjo.okinawa.jp +nishihara.okinawa.jp +ogimi.okinawa.jp +okinawa.okinawa.jp +onna.okinawa.jp +shimoji.okinawa.jp +taketomi.okinawa.jp +tarama.okinawa.jp +tokashiki.okinawa.jp +tomigusuku.okinawa.jp +tonaki.okinawa.jp +urasoe.okinawa.jp +uruma.okinawa.jp +yaese.okinawa.jp +yomitan.okinawa.jp +yonabaru.okinawa.jp +yonaguni.okinawa.jp +zamami.okinawa.jp +abeno.osaka.jp +chihayaakasaka.osaka.jp +chuo.osaka.jp +daito.osaka.jp +fujiidera.osaka.jp +habikino.osaka.jp +hannan.osaka.jp +higashiosaka.osaka.jp +higashisumiyoshi.osaka.jp +higashiyodogawa.osaka.jp +hirakata.osaka.jp +ibaraki.osaka.jp +ikeda.osaka.jp +izumi.osaka.jp +izumiotsu.osaka.jp +izumisano.osaka.jp +kadoma.osaka.jp +kaizuka.osaka.jp +kanan.osaka.jp +kashiwara.osaka.jp +katano.osaka.jp +kawachinagano.osaka.jp +kishiwada.osaka.jp +kita.osaka.jp +kumatori.osaka.jp +matsubara.osaka.jp +minato.osaka.jp +minoh.osaka.jp +misaki.osaka.jp +moriguchi.osaka.jp +neyagawa.osaka.jp +nishi.osaka.jp +nose.osaka.jp +osakasayama.osaka.jp +sakai.osaka.jp +sayama.osaka.jp +sennan.osaka.jp +settsu.osaka.jp +shijonawate.osaka.jp +shimamoto.osaka.jp +suita.osaka.jp +tadaoka.osaka.jp +taishi.osaka.jp +tajiri.osaka.jp +takaishi.osaka.jp +takatsuki.osaka.jp +tondabayashi.osaka.jp +toyonaka.osaka.jp +toyono.osaka.jp +yao.osaka.jp +ariake.saga.jp +arita.saga.jp +fukudomi.saga.jp +genkai.saga.jp +hamatama.saga.jp +hizen.saga.jp +imari.saga.jp +kamimine.saga.jp +kanzaki.saga.jp +karatsu.saga.jp +kashima.saga.jp +kitagata.saga.jp +kitahata.saga.jp +kiyama.saga.jp +kouhoku.saga.jp +kyuragi.saga.jp +nishiarita.saga.jp +ogi.saga.jp +omachi.saga.jp +ouchi.saga.jp +saga.saga.jp +shiroishi.saga.jp +taku.saga.jp +tara.saga.jp +tosu.saga.jp +yoshinogari.saga.jp +arakawa.saitama.jp +asaka.saitama.jp +chichibu.saitama.jp +fujimi.saitama.jp +fujimino.saitama.jp +fukaya.saitama.jp +hanno.saitama.jp +hanyu.saitama.jp +hasuda.saitama.jp +hatogaya.saitama.jp +hatoyama.saitama.jp +hidaka.saitama.jp +higashichichibu.saitama.jp +higashimatsuyama.saitama.jp +honjo.saitama.jp +ina.saitama.jp +iruma.saitama.jp +iwatsuki.saitama.jp +kamiizumi.saitama.jp +kamikawa.saitama.jp +kamisato.saitama.jp +kasukabe.saitama.jp +kawagoe.saitama.jp +kawaguchi.saitama.jp +kawajima.saitama.jp +kazo.saitama.jp +kitamoto.saitama.jp +koshigaya.saitama.jp +kounosu.saitama.jp +kuki.saitama.jp +kumagaya.saitama.jp +matsubushi.saitama.jp +minano.saitama.jp +misato.saitama.jp +miyashiro.saitama.jp +miyoshi.saitama.jp +moroyama.saitama.jp +nagatoro.saitama.jp +namegawa.saitama.jp +niiza.saitama.jp +ogano.saitama.jp +ogawa.saitama.jp +ogose.saitama.jp +okegawa.saitama.jp +omiya.saitama.jp +otaki.saitama.jp +ranzan.saitama.jp +ryokami.saitama.jp +saitama.saitama.jp +sakado.saitama.jp +satte.saitama.jp +sayama.saitama.jp +shiki.saitama.jp +shiraoka.saitama.jp +soka.saitama.jp +sugito.saitama.jp +toda.saitama.jp +tokigawa.saitama.jp +tokorozawa.saitama.jp +tsurugashima.saitama.jp +urawa.saitama.jp +warabi.saitama.jp +yashio.saitama.jp +yokoze.saitama.jp +yono.saitama.jp +yorii.saitama.jp +yoshida.saitama.jp +yoshikawa.saitama.jp +yoshimi.saitama.jp +aisho.shiga.jp +gamo.shiga.jp +higashiomi.shiga.jp +hikone.shiga.jp +koka.shiga.jp +konan.shiga.jp +kosei.shiga.jp +koto.shiga.jp +kusatsu.shiga.jp +maibara.shiga.jp +moriyama.shiga.jp +nagahama.shiga.jp +nishiazai.shiga.jp +notogawa.shiga.jp +omihachiman.shiga.jp +otsu.shiga.jp +ritto.shiga.jp +ryuoh.shiga.jp +takashima.shiga.jp +takatsuki.shiga.jp +torahime.shiga.jp +toyosato.shiga.jp +yasu.shiga.jp +akagi.shimane.jp +ama.shimane.jp +gotsu.shimane.jp +hamada.shimane.jp +higashiizumo.shimane.jp +hikawa.shimane.jp +hikimi.shimane.jp +izumo.shimane.jp +kakinoki.shimane.jp +masuda.shimane.jp +matsue.shimane.jp +misato.shimane.jp +nishinoshima.shimane.jp +ohda.shimane.jp +okinoshima.shimane.jp +okuizumo.shimane.jp +shimane.shimane.jp +tamayu.shimane.jp +tsuwano.shimane.jp +unnan.shimane.jp +yakumo.shimane.jp +yasugi.shimane.jp +yatsuka.shimane.jp +arai.shizuoka.jp +atami.shizuoka.jp +fuji.shizuoka.jp +fujieda.shizuoka.jp +fujikawa.shizuoka.jp +fujinomiya.shizuoka.jp +fukuroi.shizuoka.jp +gotemba.shizuoka.jp +haibara.shizuoka.jp +hamamatsu.shizuoka.jp +higashiizu.shizuoka.jp +ito.shizuoka.jp +iwata.shizuoka.jp +izu.shizuoka.jp +izunokuni.shizuoka.jp +kakegawa.shizuoka.jp +kannami.shizuoka.jp +kawanehon.shizuoka.jp +kawazu.shizuoka.jp +kikugawa.shizuoka.jp +kosai.shizuoka.jp +makinohara.shizuoka.jp +matsuzaki.shizuoka.jp +minamiizu.shizuoka.jp +mishima.shizuoka.jp +morimachi.shizuoka.jp +nishiizu.shizuoka.jp +numazu.shizuoka.jp +omaezaki.shizuoka.jp +shimada.shizuoka.jp +shimizu.shizuoka.jp +shimoda.shizuoka.jp +shizuoka.shizuoka.jp +susono.shizuoka.jp +yaizu.shizuoka.jp +yoshida.shizuoka.jp +ashikaga.tochigi.jp +bato.tochigi.jp +haga.tochigi.jp +ichikai.tochigi.jp +iwafune.tochigi.jp +kaminokawa.tochigi.jp +kanuma.tochigi.jp +karasuyama.tochigi.jp +kuroiso.tochigi.jp +mashiko.tochigi.jp +mibu.tochigi.jp +moka.tochigi.jp +motegi.tochigi.jp +nasu.tochigi.jp +nasushiobara.tochigi.jp +nikko.tochigi.jp +nishikata.tochigi.jp +nogi.tochigi.jp +ohira.tochigi.jp +ohtawara.tochigi.jp +oyama.tochigi.jp +sakura.tochigi.jp +sano.tochigi.jp +shimotsuke.tochigi.jp +shioya.tochigi.jp +takanezawa.tochigi.jp +tochigi.tochigi.jp +tsuga.tochigi.jp +ujiie.tochigi.jp +utsunomiya.tochigi.jp +yaita.tochigi.jp +aizumi.tokushima.jp +anan.tokushima.jp +ichiba.tokushima.jp +itano.tokushima.jp +kainan.tokushima.jp +komatsushima.tokushima.jp +matsushige.tokushima.jp +mima.tokushima.jp +minami.tokushima.jp +miyoshi.tokushima.jp +mugi.tokushima.jp +nakagawa.tokushima.jp +naruto.tokushima.jp +sanagochi.tokushima.jp +shishikui.tokushima.jp +tokushima.tokushima.jp +wajiki.tokushima.jp +adachi.tokyo.jp +akiruno.tokyo.jp +akishima.tokyo.jp +aogashima.tokyo.jp +arakawa.tokyo.jp +bunkyo.tokyo.jp +chiyoda.tokyo.jp +chofu.tokyo.jp +chuo.tokyo.jp +edogawa.tokyo.jp +fuchu.tokyo.jp +fussa.tokyo.jp +hachijo.tokyo.jp +hachioji.tokyo.jp +hamura.tokyo.jp +higashikurume.tokyo.jp +higashimurayama.tokyo.jp +higashiyamato.tokyo.jp +hino.tokyo.jp +hinode.tokyo.jp +hinohara.tokyo.jp +inagi.tokyo.jp +itabashi.tokyo.jp +katsushika.tokyo.jp +kita.tokyo.jp +kiyose.tokyo.jp +kodaira.tokyo.jp +koganei.tokyo.jp +kokubunji.tokyo.jp +komae.tokyo.jp +koto.tokyo.jp +kouzushima.tokyo.jp +kunitachi.tokyo.jp +machida.tokyo.jp +meguro.tokyo.jp +minato.tokyo.jp +mitaka.tokyo.jp +mizuho.tokyo.jp +musashimurayama.tokyo.jp +musashino.tokyo.jp +nakano.tokyo.jp +nerima.tokyo.jp +ogasawara.tokyo.jp +okutama.tokyo.jp +ome.tokyo.jp +oshima.tokyo.jp +ota.tokyo.jp +setagaya.tokyo.jp +shibuya.tokyo.jp +shinagawa.tokyo.jp +shinjuku.tokyo.jp +suginami.tokyo.jp +sumida.tokyo.jp +tachikawa.tokyo.jp +taito.tokyo.jp +tama.tokyo.jp +toshima.tokyo.jp +chizu.tottori.jp +hino.tottori.jp +kawahara.tottori.jp +koge.tottori.jp +kotoura.tottori.jp +misasa.tottori.jp +nanbu.tottori.jp +nichinan.tottori.jp +sakaiminato.tottori.jp +tottori.tottori.jp +wakasa.tottori.jp +yazu.tottori.jp +yonago.tottori.jp +asahi.toyama.jp +fuchu.toyama.jp +fukumitsu.toyama.jp +funahashi.toyama.jp +himi.toyama.jp +imizu.toyama.jp +inami.toyama.jp +johana.toyama.jp +kamiichi.toyama.jp +kurobe.toyama.jp +nakaniikawa.toyama.jp +namerikawa.toyama.jp +nanto.toyama.jp +nyuzen.toyama.jp +oyabe.toyama.jp +taira.toyama.jp +takaoka.toyama.jp +tateyama.toyama.jp +toga.toyama.jp +tonami.toyama.jp +toyama.toyama.jp +unazuki.toyama.jp +uozu.toyama.jp +yamada.toyama.jp +arida.wakayama.jp +aridagawa.wakayama.jp +gobo.wakayama.jp +hashimoto.wakayama.jp +hidaka.wakayama.jp +hirogawa.wakayama.jp +inami.wakayama.jp +iwade.wakayama.jp +kainan.wakayama.jp +kamitonda.wakayama.jp +katsuragi.wakayama.jp +kimino.wakayama.jp +kinokawa.wakayama.jp +kitayama.wakayama.jp +koya.wakayama.jp +koza.wakayama.jp +kozagawa.wakayama.jp +kudoyama.wakayama.jp +kushimoto.wakayama.jp +mihama.wakayama.jp +misato.wakayama.jp +nachikatsuura.wakayama.jp +shingu.wakayama.jp +shirahama.wakayama.jp +taiji.wakayama.jp +tanabe.wakayama.jp +wakayama.wakayama.jp +yuasa.wakayama.jp +yura.wakayama.jp +asahi.yamagata.jp +funagata.yamagata.jp +higashine.yamagata.jp +iide.yamagata.jp +kahoku.yamagata.jp +kaminoyama.yamagata.jp +kaneyama.yamagata.jp +kawanishi.yamagata.jp +mamurogawa.yamagata.jp +mikawa.yamagata.jp +murayama.yamagata.jp +nagai.yamagata.jp +nakayama.yamagata.jp +nanyo.yamagata.jp +nishikawa.yamagata.jp +obanazawa.yamagata.jp +oe.yamagata.jp +oguni.yamagata.jp +ohkura.yamagata.jp +oishida.yamagata.jp +sagae.yamagata.jp +sakata.yamagata.jp +sakegawa.yamagata.jp +shinjo.yamagata.jp +shirataka.yamagata.jp +shonai.yamagata.jp +takahata.yamagata.jp +tendo.yamagata.jp +tozawa.yamagata.jp +tsuruoka.yamagata.jp +yamagata.yamagata.jp +yamanobe.yamagata.jp +yonezawa.yamagata.jp +yuza.yamagata.jp +abu.yamaguchi.jp +hagi.yamaguchi.jp +hikari.yamaguchi.jp +hofu.yamaguchi.jp +iwakuni.yamaguchi.jp +kudamatsu.yamaguchi.jp +mitou.yamaguchi.jp +nagato.yamaguchi.jp +oshima.yamaguchi.jp +shimonoseki.yamaguchi.jp +shunan.yamaguchi.jp +tabuse.yamaguchi.jp +tokuyama.yamaguchi.jp +toyota.yamaguchi.jp +ube.yamaguchi.jp +yuu.yamaguchi.jp +chuo.yamanashi.jp +doshi.yamanashi.jp +fuefuki.yamanashi.jp +fujikawa.yamanashi.jp +fujikawaguchiko.yamanashi.jp +fujiyoshida.yamanashi.jp +hayakawa.yamanashi.jp +hokuto.yamanashi.jp +ichikawamisato.yamanashi.jp +kai.yamanashi.jp +kofu.yamanashi.jp +koshu.yamanashi.jp +kosuge.yamanashi.jp +minami-alps.yamanashi.jp +minobu.yamanashi.jp +nakamichi.yamanashi.jp +nanbu.yamanashi.jp +narusawa.yamanashi.jp +nirasaki.yamanashi.jp +nishikatsura.yamanashi.jp +oshino.yamanashi.jp +otsuki.yamanashi.jp +showa.yamanashi.jp +tabayama.yamanashi.jp +tsuru.yamanashi.jp +uenohara.yamanashi.jp +yamanakako.yamanashi.jp +yamanashi.yamanashi.jp + +// ke : http://www.kenic.or.ke/index.php?option=com_content&task=view&id=117&Itemid=145 +*.ke + +// kg : http://www.domain.kg/dmn_n.html +kg +org.kg +net.kg +com.kg +edu.kg +gov.kg +mil.kg + +// kh : http://www.mptc.gov.kh/dns_registration.htm +*.kh + +// ki : http://www.ki/dns/index.html +ki +edu.ki +biz.ki +net.ki +org.ki +gov.ki +info.ki +com.ki + +// km : https://en.wikipedia.org/wiki/.km +// http://www.domaine.km/documents/charte.doc +km +org.km +nom.km +gov.km +prd.km +tm.km +edu.km +mil.km +ass.km +com.km +// These are only mentioned as proposed suggestions at domaine.km, but +// https://en.wikipedia.org/wiki/.km says they're available for registration: +coop.km +asso.km +presse.km +medecin.km +notaires.km +pharmaciens.km +veterinaire.km +gouv.km + +// kn : https://en.wikipedia.org/wiki/.kn +// http://www.dot.kn/domainRules.html +kn +net.kn +org.kn +edu.kn +gov.kn + +// kp : http://www.kcce.kp/en_index.php +kp +com.kp +edu.kp +gov.kp +org.kp +rep.kp +tra.kp + +// kr : https://en.wikipedia.org/wiki/.kr +// see also: http://domain.nida.or.kr/eng/registration.jsp +kr +ac.kr +co.kr +es.kr +go.kr +hs.kr +kg.kr +mil.kr +ms.kr +ne.kr +or.kr +pe.kr +re.kr +sc.kr +// kr geographical names +busan.kr +chungbuk.kr +chungnam.kr +daegu.kr +daejeon.kr +gangwon.kr +gwangju.kr +gyeongbuk.kr +gyeonggi.kr +gyeongnam.kr +incheon.kr +jeju.kr +jeonbuk.kr +jeonnam.kr +seoul.kr +ulsan.kr + +// kw : https://en.wikipedia.org/wiki/.kw +*.kw + +// ky : http://www.icta.ky/da_ky_reg_dom.php +// Confirmed by registry 2008-06-17 +ky +edu.ky +gov.ky +com.ky +org.ky +net.ky + +// kz : https://en.wikipedia.org/wiki/.kz +// see also: http://www.nic.kz/rules/index.jsp +kz +org.kz +edu.kz +net.kz +gov.kz +mil.kz +com.kz + +// la : https://en.wikipedia.org/wiki/.la +// Submitted by registry +la +int.la +net.la +info.la +edu.la +gov.la +per.la +com.la +org.la + +// lb : https://en.wikipedia.org/wiki/.lb +// Submitted by registry +lb +com.lb +edu.lb +gov.lb +net.lb +org.lb + +// lc : https://en.wikipedia.org/wiki/.lc +// see also: http://www.nic.lc/rules.htm +lc +com.lc +net.lc +co.lc +org.lc +edu.lc +gov.lc + +// li : https://en.wikipedia.org/wiki/.li +li + +// lk : http://www.nic.lk/seclevpr.html +lk +gov.lk +sch.lk +net.lk +int.lk +com.lk +org.lk +edu.lk +ngo.lk +soc.lk +web.lk +ltd.lk +assn.lk +grp.lk +hotel.lk +ac.lk + +// lr : http://psg.com/dns/lr/lr.txt +// Submitted by registry +lr +com.lr +edu.lr +gov.lr +org.lr +net.lr + +// ls : https://en.wikipedia.org/wiki/.ls +ls +co.ls +org.ls + +// lt : https://en.wikipedia.org/wiki/.lt +lt +// gov.lt : http://www.gov.lt/index_en.php +gov.lt + +// lu : http://www.dns.lu/en/ +lu + +// lv : http://www.nic.lv/DNS/En/generic.php +lv +com.lv +edu.lv +gov.lv +org.lv +mil.lv +id.lv +net.lv +asn.lv +conf.lv + +// ly : http://www.nic.ly/regulations.php +ly +com.ly +net.ly +gov.ly +plc.ly +edu.ly +sch.ly +med.ly +org.ly +id.ly + +// ma : https://en.wikipedia.org/wiki/.ma +// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf +ma +co.ma +net.ma +gov.ma +org.ma +ac.ma +press.ma + +// mc : http://www.nic.mc/ +mc +tm.mc +asso.mc + +// md : https://en.wikipedia.org/wiki/.md +md + +// me : https://en.wikipedia.org/wiki/.me +me +co.me +net.me +org.me +edu.me +ac.me +gov.me +its.me +priv.me + +// mg : http://nic.mg/nicmg/?page_id=39 +mg +org.mg +nom.mg +gov.mg +prd.mg +tm.mg +edu.mg +mil.mg +com.mg +co.mg + +// mh : https://en.wikipedia.org/wiki/.mh +mh + +// mil : https://en.wikipedia.org/wiki/.mil +mil + +// mk : https://en.wikipedia.org/wiki/.mk +// see also: http://dns.marnet.net.mk/postapka.php +mk +com.mk +org.mk +net.mk +edu.mk +gov.mk +inf.mk +name.mk + +// ml : http://www.gobin.info/domainname/ml-template.doc +// see also: https://en.wikipedia.org/wiki/.ml +ml +com.ml +edu.ml +gouv.ml +gov.ml +net.ml +org.ml +presse.ml + +// mm : https://en.wikipedia.org/wiki/.mm +*.mm + +// mn : https://en.wikipedia.org/wiki/.mn +mn +gov.mn +edu.mn +org.mn + +// mo : http://www.monic.net.mo/ +mo +com.mo +net.mo +org.mo +edu.mo +gov.mo + +// mobi : https://en.wikipedia.org/wiki/.mobi +mobi + +// mp : http://www.dot.mp/ +// Confirmed by registry 2008-06-17 +mp + +// mq : https://en.wikipedia.org/wiki/.mq +mq + +// mr : https://en.wikipedia.org/wiki/.mr +mr +gov.mr + +// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf +ms +com.ms +edu.ms +gov.ms +net.ms +org.ms + +// mt : https://www.nic.org.mt/go/policy +// Submitted by registry +mt +com.mt +edu.mt +net.mt +org.mt + +// mu : https://en.wikipedia.org/wiki/.mu +mu +com.mu +net.mu +org.mu +gov.mu +ac.mu +co.mu +or.mu + +// museum : http://about.museum/naming/ +// http://index.museum/ +museum +academy.museum +agriculture.museum +air.museum +airguard.museum +alabama.museum +alaska.museum +amber.museum +ambulance.museum +american.museum +americana.museum +americanantiques.museum +americanart.museum +amsterdam.museum +and.museum +annefrank.museum +anthro.museum +anthropology.museum +antiques.museum +aquarium.museum +arboretum.museum +archaeological.museum +archaeology.museum +architecture.museum +art.museum +artanddesign.museum +artcenter.museum +artdeco.museum +arteducation.museum +artgallery.museum +arts.museum +artsandcrafts.museum +asmatart.museum +assassination.museum +assisi.museum +association.museum +astronomy.museum +atlanta.museum +austin.museum +australia.museum +automotive.museum +aviation.museum +axis.museum +badajoz.museum +baghdad.museum +bahn.museum +bale.museum +baltimore.museum +barcelona.museum +baseball.museum +basel.museum +baths.museum +bauern.museum +beauxarts.museum +beeldengeluid.museum +bellevue.museum +bergbau.museum +berkeley.museum +berlin.museum +bern.museum +bible.museum +bilbao.museum +bill.museum +birdart.museum +birthplace.museum +bonn.museum +boston.museum +botanical.museum +botanicalgarden.museum +botanicgarden.museum +botany.museum +brandywinevalley.museum +brasil.museum +bristol.museum +british.museum +britishcolumbia.museum +broadcast.museum +brunel.museum +brussel.museum +brussels.museum +bruxelles.museum +building.museum +burghof.museum +bus.museum +bushey.museum +cadaques.museum +california.museum +cambridge.museum +can.museum +canada.museum +capebreton.museum +carrier.museum +cartoonart.museum +casadelamoneda.museum +castle.museum +castres.museum +celtic.museum +center.museum +chattanooga.museum +cheltenham.museum +chesapeakebay.museum +chicago.museum +children.museum +childrens.museum +childrensgarden.museum +chiropractic.museum +chocolate.museum +christiansburg.museum +cincinnati.museum +cinema.museum +circus.museum +civilisation.museum +civilization.museum +civilwar.museum +clinton.museum +clock.museum +coal.museum +coastaldefence.museum +cody.museum +coldwar.museum +collection.museum +colonialwilliamsburg.museum +coloradoplateau.museum +columbia.museum +columbus.museum +communication.museum +communications.museum +community.museum +computer.museum +computerhistory.museum +comunicações.museum +contemporary.museum +contemporaryart.museum +convent.museum +copenhagen.museum +corporation.museum +correios-e-telecomunicações.museum +corvette.museum +costume.museum +countryestate.museum +county.museum +crafts.museum +cranbrook.museum +creation.museum +cultural.museum +culturalcenter.museum +culture.museum +cyber.museum +cymru.museum +dali.museum +dallas.museum +database.museum +ddr.museum +decorativearts.museum +delaware.museum +delmenhorst.museum +denmark.museum +depot.museum +design.museum +detroit.museum +dinosaur.museum +discovery.museum +dolls.museum +donostia.museum +durham.museum +eastafrica.museum +eastcoast.museum +education.museum +educational.museum +egyptian.museum +eisenbahn.museum +elburg.museum +elvendrell.museum +embroidery.museum +encyclopedic.museum +england.museum +entomology.museum +environment.museum +environmentalconservation.museum +epilepsy.museum +essex.museum +estate.museum +ethnology.museum +exeter.museum +exhibition.museum +family.museum +farm.museum +farmequipment.museum +farmers.museum +farmstead.museum +field.museum +figueres.museum +filatelia.museum +film.museum +fineart.museum +finearts.museum +finland.museum +flanders.museum +florida.museum +force.museum +fortmissoula.museum +fortworth.museum +foundation.museum +francaise.museum +frankfurt.museum +franziskaner.museum +freemasonry.museum +freiburg.museum +fribourg.museum +frog.museum +fundacio.museum +furniture.museum +gallery.museum +garden.museum +gateway.museum +geelvinck.museum +gemological.museum +geology.museum +georgia.museum +giessen.museum +glas.museum +glass.museum +gorge.museum +grandrapids.museum +graz.museum +guernsey.museum +halloffame.museum +hamburg.museum +handson.museum +harvestcelebration.museum +hawaii.museum +health.museum +heimatunduhren.museum +hellas.museum +helsinki.museum +hembygdsforbund.museum +heritage.museum +histoire.museum +historical.museum +historicalsociety.museum +historichouses.museum +historisch.museum +historisches.museum +history.museum +historyofscience.museum +horology.museum +house.museum +humanities.museum +illustration.museum +imageandsound.museum +indian.museum +indiana.museum +indianapolis.museum +indianmarket.museum +intelligence.museum +interactive.museum +iraq.museum +iron.museum +isleofman.museum +jamison.museum +jefferson.museum +jerusalem.museum +jewelry.museum +jewish.museum +jewishart.museum +jfk.museum +journalism.museum +judaica.museum +judygarland.museum +juedisches.museum +juif.museum +karate.museum +karikatur.museum +kids.museum +koebenhavn.museum +koeln.museum +kunst.museum +kunstsammlung.museum +kunstunddesign.museum +labor.museum +labour.museum +lajolla.museum +lancashire.museum +landes.museum +lans.museum +läns.museum +larsson.museum +lewismiller.museum +lincoln.museum +linz.museum +living.museum +livinghistory.museum +localhistory.museum +london.museum +losangeles.museum +louvre.museum +loyalist.museum +lucerne.museum +luxembourg.museum +luzern.museum +mad.museum +madrid.museum +mallorca.museum +manchester.museum +mansion.museum +mansions.museum +manx.museum +marburg.museum +maritime.museum +maritimo.museum +maryland.museum +marylhurst.museum +media.museum +medical.museum +medizinhistorisches.museum +meeres.museum +memorial.museum +mesaverde.museum +michigan.museum +midatlantic.museum +military.museum +mill.museum +miners.museum +mining.museum +minnesota.museum +missile.museum +missoula.museum +modern.museum +moma.museum +money.museum +monmouth.museum +monticello.museum +montreal.museum +moscow.museum +motorcycle.museum +muenchen.museum +muenster.museum +mulhouse.museum +muncie.museum +museet.museum +museumcenter.museum +museumvereniging.museum +music.museum +national.museum +nationalfirearms.museum +nationalheritage.museum +nativeamerican.museum +naturalhistory.museum +naturalhistorymuseum.museum +naturalsciences.museum +nature.museum +naturhistorisches.museum +natuurwetenschappen.museum +naumburg.museum +naval.museum +nebraska.museum +neues.museum +newhampshire.museum +newjersey.museum +newmexico.museum +newport.museum +newspaper.museum +newyork.museum +niepce.museum +norfolk.museum +north.museum +nrw.museum +nuernberg.museum +nuremberg.museum +nyc.museum +nyny.museum +oceanographic.museum +oceanographique.museum +omaha.museum +online.museum +ontario.museum +openair.museum +oregon.museum +oregontrail.museum +otago.museum +oxford.museum +pacific.museum +paderborn.museum +palace.museum +paleo.museum +palmsprings.museum +panama.museum +paris.museum +pasadena.museum +pharmacy.museum +philadelphia.museum +philadelphiaarea.museum +philately.museum +phoenix.museum +photography.museum +pilots.museum +pittsburgh.museum +planetarium.museum +plantation.museum +plants.museum +plaza.museum +portal.museum +portland.museum +portlligat.museum +posts-and-telecommunications.museum +preservation.museum +presidio.museum +press.museum +project.museum +public.museum +pubol.museum +quebec.museum +railroad.museum +railway.museum +research.museum +resistance.museum +riodejaneiro.museum +rochester.museum +rockart.museum +roma.museum +russia.museum +saintlouis.museum +salem.museum +salvadordali.museum +salzburg.museum +sandiego.museum +sanfrancisco.museum +santabarbara.museum +santacruz.museum +santafe.museum +saskatchewan.museum +satx.museum +savannahga.museum +schlesisches.museum +schoenbrunn.museum +schokoladen.museum +school.museum +schweiz.museum +science.museum +scienceandhistory.museum +scienceandindustry.museum +sciencecenter.museum +sciencecenters.museum +science-fiction.museum +sciencehistory.museum +sciences.museum +sciencesnaturelles.museum +scotland.museum +seaport.museum +settlement.museum +settlers.museum +shell.museum +sherbrooke.museum +sibenik.museum +silk.museum +ski.museum +skole.museum +society.museum +sologne.museum +soundandvision.museum +southcarolina.museum +southwest.museum +space.museum +spy.museum +square.museum +stadt.museum +stalbans.museum +starnberg.museum +state.museum +stateofdelaware.museum +station.museum +steam.museum +steiermark.museum +stjohn.museum +stockholm.museum +stpetersburg.museum +stuttgart.museum +suisse.museum +surgeonshall.museum +surrey.museum +svizzera.museum +sweden.museum +sydney.museum +tank.museum +tcm.museum +technology.museum +telekommunikation.museum +television.museum +texas.museum +textile.museum +theater.museum +time.museum +timekeeping.museum +topology.museum +torino.museum +touch.museum +town.museum +transport.museum +tree.museum +trolley.museum +trust.museum +trustee.museum +uhren.museum +ulm.museum +undersea.museum +university.museum +usa.museum +usantiques.museum +usarts.museum +uscountryestate.museum +usculture.museum +usdecorativearts.museum +usgarden.museum +ushistory.museum +ushuaia.museum +uslivinghistory.museum +utah.museum +uvic.museum +valley.museum +vantaa.museum +versailles.museum +viking.museum +village.museum +virginia.museum +virtual.museum +virtuel.museum +vlaanderen.museum +volkenkunde.museum +wales.museum +wallonie.museum +war.museum +washingtondc.museum +watchandclock.museum +watch-and-clock.museum +western.museum +westfalen.museum +whaling.museum +wildlife.museum +williamsburg.museum +windmill.museum +workshop.museum +york.museum +yorkshire.museum +yosemite.museum +youth.museum +zoological.museum +zoology.museum +ירושלים.museum +иком.museum + +// mv : https://en.wikipedia.org/wiki/.mv +// "mv" included because, contra Wikipedia, google.mv exists. +mv +aero.mv +biz.mv +com.mv +coop.mv +edu.mv +gov.mv +info.mv +int.mv +mil.mv +museum.mv +name.mv +net.mv +org.mv +pro.mv + +// mw : http://www.registrar.mw/ +mw +ac.mw +biz.mw +co.mw +com.mw +coop.mw +edu.mw +gov.mw +int.mw +museum.mw +net.mw +org.mw + +// mx : http://www.nic.mx/ +// Submitted by registry +mx +com.mx +org.mx +gob.mx +edu.mx +net.mx + +// my : http://www.mynic.net.my/ +my +com.my +net.my +org.my +gov.my +edu.my +mil.my +name.my + +// mz : http://www.gobin.info/domainname/mz-template.doc +*.mz +!teledata.mz + +// na : http://www.na-nic.com.na/ +// http://www.info.na/domain/ +na +info.na +pro.na +name.na +school.na +or.na +dr.na +us.na +mx.na +ca.na +in.na +cc.na +tv.na +ws.na +mobi.na +co.na +com.na +org.na + +// name : has 2nd-level tlds, but there's no list of them +name + +// nc : http://www.cctld.nc/ +nc +asso.nc + +// ne : https://en.wikipedia.org/wiki/.ne +ne + +// net : https://en.wikipedia.org/wiki/.net +net + +// nf : https://en.wikipedia.org/wiki/.nf +nf +com.nf +net.nf +per.nf +rec.nf +web.nf +arts.nf +firm.nf +info.nf +other.nf +store.nf + +// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds +ng +com.ng +edu.ng +gov.ng +i.ng +mil.ng +mobi.ng +name.ng +net.ng +org.ng +sch.ng + +// ni : http://www.nic.ni/ +com.ni +gob.ni +edu.ni +org.ni +nom.ni +net.ni +mil.ni +co.ni +biz.ni +web.ni +int.ni +ac.ni +in.ni +info.ni + +// nl : https://en.wikipedia.org/wiki/.nl +// https://www.sidn.nl/ +// ccTLD for the Netherlands +nl + +// BV.nl will be a registry for dutch BV's (besloten vennootschap) +bv.nl + +// no : http://www.norid.no/regelverk/index.en.html +// The Norwegian registry has declined to notify us of updates. The web pages +// referenced below are the official source of the data. There is also an +// announce mailing list: +// https://postlister.uninett.no/sympa/info/norid-diskusjon +no +// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html +fhs.no +vgs.no +fylkesbibl.no +folkebibl.no +museum.no +idrett.no +priv.no +// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html +mil.no +stat.no +dep.no +kommune.no +herad.no +// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html +// counties +aa.no +ah.no +bu.no +fm.no +hl.no +hm.no +jan-mayen.no +mr.no +nl.no +nt.no +of.no +ol.no +oslo.no +rl.no +sf.no +st.no +svalbard.no +tm.no +tr.no +va.no +vf.no +// primary and lower secondary schools per county +gs.aa.no +gs.ah.no +gs.bu.no +gs.fm.no +gs.hl.no +gs.hm.no +gs.jan-mayen.no +gs.mr.no +gs.nl.no +gs.nt.no +gs.of.no +gs.ol.no +gs.oslo.no +gs.rl.no +gs.sf.no +gs.st.no +gs.svalbard.no +gs.tm.no +gs.tr.no +gs.va.no +gs.vf.no +// cities +akrehamn.no +åkrehamn.no +algard.no +ålgård.no +arna.no +brumunddal.no +bryne.no +bronnoysund.no +brønnøysund.no +drobak.no +drøbak.no +egersund.no +fetsund.no +floro.no +florø.no +fredrikstad.no +hokksund.no +honefoss.no +hønefoss.no +jessheim.no +jorpeland.no +jørpeland.no +kirkenes.no +kopervik.no +krokstadelva.no +langevag.no +langevåg.no +leirvik.no +mjondalen.no +mjøndalen.no +mo-i-rana.no +mosjoen.no +mosjøen.no +nesoddtangen.no +orkanger.no +osoyro.no +osøyro.no +raholt.no +råholt.no +sandnessjoen.no +sandnessjøen.no +skedsmokorset.no +slattum.no +spjelkavik.no +stathelle.no +stavern.no +stjordalshalsen.no +stjørdalshalsen.no +tananger.no +tranby.no +vossevangen.no +// communities +afjord.no +åfjord.no +agdenes.no +al.no +ål.no +alesund.no +ålesund.no +alstahaug.no +alta.no +áltá.no +alaheadju.no +álaheadju.no +alvdal.no +amli.no +åmli.no +amot.no +åmot.no +andebu.no +andoy.no +andøy.no +andasuolo.no +ardal.no +årdal.no +aremark.no +arendal.no +ås.no +aseral.no +åseral.no +asker.no +askim.no +askvoll.no +askoy.no +askøy.no +asnes.no +åsnes.no +audnedaln.no +aukra.no +aure.no +aurland.no +aurskog-holand.no +aurskog-høland.no +austevoll.no +austrheim.no +averoy.no +averøy.no +balestrand.no +ballangen.no +balat.no +bálát.no +balsfjord.no +bahccavuotna.no +báhccavuotna.no +bamble.no +bardu.no +beardu.no +beiarn.no +bajddar.no +bájddar.no +baidar.no +báidár.no +berg.no +bergen.no +berlevag.no +berlevåg.no +bearalvahki.no +bearalváhki.no +bindal.no +birkenes.no +bjarkoy.no +bjarkøy.no +bjerkreim.no +bjugn.no +bodo.no +bodø.no +badaddja.no +bådåddjå.no +budejju.no +bokn.no +bremanger.no +bronnoy.no +brønnøy.no +bygland.no +bykle.no +barum.no +bærum.no +bo.telemark.no +bø.telemark.no +bo.nordland.no +bø.nordland.no +bievat.no +bievát.no +bomlo.no +bømlo.no +batsfjord.no +båtsfjord.no +bahcavuotna.no +báhcavuotna.no +dovre.no +drammen.no +drangedal.no +dyroy.no +dyrøy.no +donna.no +dønna.no +eid.no +eidfjord.no +eidsberg.no +eidskog.no +eidsvoll.no +eigersund.no +elverum.no +enebakk.no +engerdal.no +etne.no +etnedal.no +evenes.no +evenassi.no +evenášši.no +evje-og-hornnes.no +farsund.no +fauske.no +fuossko.no +fuoisku.no +fedje.no +fet.no +finnoy.no +finnøy.no +fitjar.no +fjaler.no +fjell.no +flakstad.no +flatanger.no +flekkefjord.no +flesberg.no +flora.no +fla.no +flå.no +folldal.no +forsand.no +fosnes.no +frei.no +frogn.no +froland.no +frosta.no +frana.no +fræna.no +froya.no +frøya.no +fusa.no +fyresdal.no +forde.no +førde.no +gamvik.no +gangaviika.no +gáŋgaviika.no +gaular.no +gausdal.no +gildeskal.no +gildeskål.no +giske.no +gjemnes.no +gjerdrum.no +gjerstad.no +gjesdal.no +gjovik.no +gjøvik.no +gloppen.no +gol.no +gran.no +grane.no +granvin.no +gratangen.no +grimstad.no +grong.no +kraanghke.no +kråanghke.no +grue.no +gulen.no +hadsel.no +halden.no +halsa.no +hamar.no +hamaroy.no +habmer.no +hábmer.no +hapmir.no +hápmir.no +hammerfest.no +hammarfeasta.no +hámmárfeasta.no +haram.no +hareid.no +harstad.no +hasvik.no +aknoluokta.no +ákŋoluokta.no +hattfjelldal.no +aarborte.no +haugesund.no +hemne.no +hemnes.no +hemsedal.no +heroy.more-og-romsdal.no +herøy.møre-og-romsdal.no +heroy.nordland.no +herøy.nordland.no +hitra.no +hjartdal.no +hjelmeland.no +hobol.no +hobøl.no +hof.no +hol.no +hole.no +holmestrand.no +holtalen.no +holtålen.no +hornindal.no +horten.no +hurdal.no +hurum.no +hvaler.no +hyllestad.no +hagebostad.no +hægebostad.no +hoyanger.no +høyanger.no +hoylandet.no +høylandet.no +ha.no +hå.no +ibestad.no +inderoy.no +inderøy.no +iveland.no +jevnaker.no +jondal.no +jolster.no +jølster.no +karasjok.no +karasjohka.no +kárášjohka.no +karlsoy.no +galsa.no +gálsá.no +karmoy.no +karmøy.no +kautokeino.no +guovdageaidnu.no +klepp.no +klabu.no +klæbu.no +kongsberg.no +kongsvinger.no +kragero.no +kragerø.no +kristiansand.no +kristiansund.no +krodsherad.no +krødsherad.no +kvalsund.no +rahkkeravju.no +ráhkkerávju.no +kvam.no +kvinesdal.no +kvinnherad.no +kviteseid.no +kvitsoy.no +kvitsøy.no +kvafjord.no +kvæfjord.no +giehtavuoatna.no +kvanangen.no +kvænangen.no +navuotna.no +návuotna.no +kafjord.no +kåfjord.no +gaivuotna.no +gáivuotna.no +larvik.no +lavangen.no +lavagis.no +loabat.no +loabát.no +lebesby.no +davvesiida.no +leikanger.no +leirfjord.no +leka.no +leksvik.no +lenvik.no +leangaviika.no +leaŋgaviika.no +lesja.no +levanger.no +lier.no +lierne.no +lillehammer.no +lillesand.no +lindesnes.no +lindas.no +lindås.no +lom.no +loppa.no +lahppi.no +láhppi.no +lund.no +lunner.no +luroy.no +lurøy.no +luster.no +lyngdal.no +lyngen.no +ivgu.no +lardal.no +lerdal.no +lærdal.no +lodingen.no +lødingen.no +lorenskog.no +lørenskog.no +loten.no +løten.no +malvik.no +masoy.no +måsøy.no +muosat.no +muosát.no +mandal.no +marker.no +marnardal.no +masfjorden.no +meland.no +meldal.no +melhus.no +meloy.no +meløy.no +meraker.no +meråker.no +moareke.no +moåreke.no +midsund.no +midtre-gauldal.no +modalen.no +modum.no +molde.no +moskenes.no +moss.no +mosvik.no +malselv.no +målselv.no +malatvuopmi.no +málatvuopmi.no +namdalseid.no +aejrie.no +namsos.no +namsskogan.no +naamesjevuemie.no +nååmesjevuemie.no +laakesvuemie.no +nannestad.no +narvik.no +narviika.no +naustdal.no +nedre-eiker.no +nes.akershus.no +nes.buskerud.no +nesna.no +nesodden.no +nesseby.no +unjarga.no +unjárga.no +nesset.no +nissedal.no +nittedal.no +nord-aurdal.no +nord-fron.no +nord-odal.no +norddal.no +nordkapp.no +davvenjarga.no +davvenjárga.no +nordre-land.no +nordreisa.no +raisa.no +ráisa.no +nore-og-uvdal.no +notodden.no +naroy.no +nærøy.no +notteroy.no +nøtterøy.no +odda.no +oksnes.no +øksnes.no +oppdal.no +oppegard.no +oppegård.no +orkdal.no +orland.no +ørland.no +orskog.no +ørskog.no +orsta.no +ørsta.no +os.hedmark.no +os.hordaland.no +osen.no +osteroy.no +osterøy.no +ostre-toten.no +østre-toten.no +overhalla.no +ovre-eiker.no +øvre-eiker.no +oyer.no +øyer.no +oygarden.no +øygarden.no +oystre-slidre.no +øystre-slidre.no +porsanger.no +porsangu.no +porsáŋgu.no +porsgrunn.no +radoy.no +radøy.no +rakkestad.no +rana.no +ruovat.no +randaberg.no +rauma.no +rendalen.no +rennebu.no +rennesoy.no +rennesøy.no +rindal.no +ringebu.no +ringerike.no +ringsaker.no +rissa.no +risor.no +risør.no +roan.no +rollag.no +rygge.no +ralingen.no +rælingen.no +rodoy.no +rødøy.no +romskog.no +rømskog.no +roros.no +røros.no +rost.no +røst.no +royken.no +røyken.no +royrvik.no +røyrvik.no +rade.no +råde.no +salangen.no +siellak.no +saltdal.no +salat.no +sálát.no +sálat.no +samnanger.no +sande.more-og-romsdal.no +sande.møre-og-romsdal.no +sande.vestfold.no +sandefjord.no +sandnes.no +sandoy.no +sandøy.no +sarpsborg.no +sauda.no +sauherad.no +sel.no +selbu.no +selje.no +seljord.no +sigdal.no +siljan.no +sirdal.no +skaun.no +skedsmo.no +ski.no +skien.no +skiptvet.no +skjervoy.no +skjervøy.no +skierva.no +skiervá.no +skjak.no +skjåk.no +skodje.no +skanland.no +skånland.no +skanit.no +skánit.no +smola.no +smøla.no +snillfjord.no +snasa.no +snåsa.no +snoasa.no +snaase.no +snåase.no +sogndal.no +sokndal.no +sola.no +solund.no +songdalen.no +sortland.no +spydeberg.no +stange.no +stavanger.no +steigen.no +steinkjer.no +stjordal.no +stjørdal.no +stokke.no +stor-elvdal.no +stord.no +stordal.no +storfjord.no +omasvuotna.no +strand.no +stranda.no +stryn.no +sula.no +suldal.no +sund.no +sunndal.no +surnadal.no +sveio.no +svelvik.no +sykkylven.no +sogne.no +søgne.no +somna.no +sømna.no +sondre-land.no +søndre-land.no +sor-aurdal.no +sør-aurdal.no +sor-fron.no +sør-fron.no +sor-odal.no +sør-odal.no +sor-varanger.no +sør-varanger.no +matta-varjjat.no +mátta-várjjat.no +sorfold.no +sørfold.no +sorreisa.no +sørreisa.no +sorum.no +sørum.no +tana.no +deatnu.no +time.no +tingvoll.no +tinn.no +tjeldsund.no +dielddanuorri.no +tjome.no +tjøme.no +tokke.no +tolga.no +torsken.no +tranoy.no +tranøy.no +tromso.no +tromsø.no +tromsa.no +romsa.no +trondheim.no +troandin.no +trysil.no +trana.no +træna.no +trogstad.no +trøgstad.no +tvedestrand.no +tydal.no +tynset.no +tysfjord.no +divtasvuodna.no +divttasvuotna.no +tysnes.no +tysvar.no +tysvær.no +tonsberg.no +tønsberg.no +ullensaker.no +ullensvang.no +ulvik.no +utsira.no +vadso.no +vadsø.no +cahcesuolo.no +čáhcesuolo.no +vaksdal.no +valle.no +vang.no +vanylven.no +vardo.no +vardø.no +varggat.no +várggát.no +vefsn.no +vaapste.no +vega.no +vegarshei.no +vegårshei.no +vennesla.no +verdal.no +verran.no +vestby.no +vestnes.no +vestre-slidre.no +vestre-toten.no +vestvagoy.no +vestvågøy.no +vevelstad.no +vik.no +vikna.no +vindafjord.no +volda.no +voss.no +varoy.no +værøy.no +vagan.no +vågan.no +voagat.no +vagsoy.no +vågsøy.no +vaga.no +vågå.no +valer.ostfold.no +våler.østfold.no +valer.hedmark.no +våler.hedmark.no + +// np : http://www.mos.com.np/register.html +*.np + +// nr : http://cenpac.net.nr/dns/index.html +// Submitted by registry +nr +biz.nr +info.nr +gov.nr +edu.nr +org.nr +net.nr +com.nr + +// nu : https://en.wikipedia.org/wiki/.nu +nu + +// nz : https://en.wikipedia.org/wiki/.nz +// Submitted by registry +nz +ac.nz +co.nz +cri.nz +geek.nz +gen.nz +govt.nz +health.nz +iwi.nz +kiwi.nz +maori.nz +mil.nz +māori.nz +net.nz +org.nz +parliament.nz +school.nz + +// om : https://en.wikipedia.org/wiki/.om +om +co.om +com.om +edu.om +gov.om +med.om +museum.om +net.om +org.om +pro.om + +// org : https://en.wikipedia.org/wiki/.org +org + +// pa : http://www.nic.pa/ +// Some additional second level "domains" resolve directly as hostnames, such as +// pannet.pa, so we add a rule for "pa". +pa +ac.pa +gob.pa +com.pa +org.pa +sld.pa +edu.pa +net.pa +ing.pa +abo.pa +med.pa +nom.pa + +// pe : https://www.nic.pe/InformeFinalComision.pdf +pe +edu.pe +gob.pe +nom.pe +mil.pe +org.pe +com.pe +net.pe + +// pf : http://www.gobin.info/domainname/formulaire-pf.pdf +pf +com.pf +org.pf +edu.pf + +// pg : https://en.wikipedia.org/wiki/.pg +*.pg + +// ph : http://www.domains.ph/FAQ2.asp +// Submitted by registry +ph +com.ph +net.ph +org.ph +gov.ph +edu.ph +ngo.ph +mil.ph +i.ph + +// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK +pk +com.pk +net.pk +edu.pk +org.pk +fam.pk +biz.pk +web.pk +gov.pk +gob.pk +gok.pk +gon.pk +gop.pk +gos.pk +info.pk + +// pl http://www.dns.pl/english/index.html +// Submitted by registry +pl +com.pl +net.pl +org.pl +// pl functional domains (http://www.dns.pl/english/index.html) +aid.pl +agro.pl +atm.pl +auto.pl +biz.pl +edu.pl +gmina.pl +gsm.pl +info.pl +mail.pl +miasta.pl +media.pl +mil.pl +nieruchomosci.pl +nom.pl +pc.pl +powiat.pl +priv.pl +realestate.pl +rel.pl +sex.pl +shop.pl +sklep.pl +sos.pl +szkola.pl +targi.pl +tm.pl +tourism.pl +travel.pl +turystyka.pl +// Government domains +gov.pl +ap.gov.pl +ic.gov.pl +is.gov.pl +us.gov.pl +kmpsp.gov.pl +kppsp.gov.pl +kwpsp.gov.pl +psp.gov.pl +wskr.gov.pl +kwp.gov.pl +mw.gov.pl +ug.gov.pl +um.gov.pl +umig.gov.pl +ugim.gov.pl +upow.gov.pl +uw.gov.pl +starostwo.gov.pl +pa.gov.pl +po.gov.pl +psse.gov.pl +pup.gov.pl +rzgw.gov.pl +sa.gov.pl +so.gov.pl +sr.gov.pl +wsa.gov.pl +sko.gov.pl +uzs.gov.pl +wiih.gov.pl +winb.gov.pl +pinb.gov.pl +wios.gov.pl +witd.gov.pl +wzmiuw.gov.pl +piw.gov.pl +wiw.gov.pl +griw.gov.pl +wif.gov.pl +oum.gov.pl +sdn.gov.pl +zp.gov.pl +uppo.gov.pl +mup.gov.pl +wuoz.gov.pl +konsulat.gov.pl +oirm.gov.pl +// pl regional domains (http://www.dns.pl/english/index.html) +augustow.pl +babia-gora.pl +bedzin.pl +beskidy.pl +bialowieza.pl +bialystok.pl +bielawa.pl +bieszczady.pl +boleslawiec.pl +bydgoszcz.pl +bytom.pl +cieszyn.pl +czeladz.pl +czest.pl +dlugoleka.pl +elblag.pl +elk.pl +glogow.pl +gniezno.pl +gorlice.pl +grajewo.pl +ilawa.pl +jaworzno.pl +jelenia-gora.pl +jgora.pl +kalisz.pl +kazimierz-dolny.pl +karpacz.pl +kartuzy.pl +kaszuby.pl +katowice.pl +kepno.pl +ketrzyn.pl +klodzko.pl +kobierzyce.pl +kolobrzeg.pl +konin.pl +konskowola.pl +kutno.pl +lapy.pl +lebork.pl +legnica.pl +lezajsk.pl +limanowa.pl +lomza.pl +lowicz.pl +lubin.pl +lukow.pl +malbork.pl +malopolska.pl +mazowsze.pl +mazury.pl +mielec.pl +mielno.pl +mragowo.pl +naklo.pl +nowaruda.pl +nysa.pl +olawa.pl +olecko.pl +olkusz.pl +olsztyn.pl +opoczno.pl +opole.pl +ostroda.pl +ostroleka.pl +ostrowiec.pl +ostrowwlkp.pl +pila.pl +pisz.pl +podhale.pl +podlasie.pl +polkowice.pl +pomorze.pl +pomorskie.pl +prochowice.pl +pruszkow.pl +przeworsk.pl +pulawy.pl +radom.pl +rawa-maz.pl +rybnik.pl +rzeszow.pl +sanok.pl +sejny.pl +slask.pl +slupsk.pl +sosnowiec.pl +stalowa-wola.pl +skoczow.pl +starachowice.pl +stargard.pl +suwalki.pl +swidnica.pl +swiebodzin.pl +swinoujscie.pl +szczecin.pl +szczytno.pl +tarnobrzeg.pl +tgory.pl +turek.pl +tychy.pl +ustka.pl +walbrzych.pl +warmia.pl +warszawa.pl +waw.pl +wegrow.pl +wielun.pl +wlocl.pl +wloclawek.pl +wodzislaw.pl +wolomin.pl +wroclaw.pl +zachpomor.pl +zagan.pl +zarow.pl +zgora.pl +zgorzelec.pl + +// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +pm + +// pn : http://www.government.pn/PnRegistry/policies.htm +pn +gov.pn +co.pn +org.pn +edu.pn +net.pn + +// post : https://en.wikipedia.org/wiki/.post +post + +// pr : http://www.nic.pr/index.asp?f=1 +pr +com.pr +net.pr +org.pr +gov.pr +edu.pr +isla.pr +pro.pr +biz.pr +info.pr +name.pr +// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr +est.pr +prof.pr +ac.pr + +// pro : http://registry.pro/get-pro +pro +aaa.pro +aca.pro +acct.pro +avocat.pro +bar.pro +cpa.pro +eng.pro +jur.pro +law.pro +med.pro +recht.pro + +// ps : https://en.wikipedia.org/wiki/.ps +// http://www.nic.ps/registration/policy.html#reg +ps +edu.ps +gov.ps +sec.ps +plo.ps +com.ps +org.ps +net.ps + +// pt : http://online.dns.pt/dns/start_dns +pt +net.pt +gov.pt +org.pt +edu.pt +int.pt +publ.pt +com.pt +nome.pt + +// pw : https://en.wikipedia.org/wiki/.pw +pw +co.pw +ne.pw +or.pw +ed.pw +go.pw +belau.pw + +// py : http://www.nic.py/pautas.html#seccion_9 +// Submitted by registry +py +com.py +coop.py +edu.py +gov.py +mil.py +net.py +org.py + +// qa : http://domains.qa/en/ +qa +com.qa +edu.qa +gov.qa +mil.qa +name.qa +net.qa +org.qa +sch.qa + +// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs +re +asso.re +com.re +nom.re + +// ro : http://www.rotld.ro/ +ro +arts.ro +com.ro +firm.ro +info.ro +nom.ro +nt.ro +org.ro +rec.ro +store.ro +tm.ro +www.ro + +// rs : https://www.rnids.rs/en/domains/national-domains +rs +ac.rs +co.rs +edu.rs +gov.rs +in.rs +org.rs + +// ru : http://www.cctld.ru/ru/docs/aktiv_8.php +// Industry domains +ru +ac.ru +com.ru +edu.ru +int.ru +net.ru +org.ru +pp.ru +// Geographical domains +adygeya.ru +altai.ru +amur.ru +arkhangelsk.ru +astrakhan.ru +bashkiria.ru +belgorod.ru +bir.ru +bryansk.ru +buryatia.ru +cbg.ru +chel.ru +chelyabinsk.ru +chita.ru +chukotka.ru +chuvashia.ru +dagestan.ru +dudinka.ru +e-burg.ru +grozny.ru +irkutsk.ru +ivanovo.ru +izhevsk.ru +jar.ru +joshkar-ola.ru +kalmykia.ru +kaluga.ru +kamchatka.ru +karelia.ru +kazan.ru +kchr.ru +kemerovo.ru +khabarovsk.ru +khakassia.ru +khv.ru +kirov.ru +koenig.ru +komi.ru +kostroma.ru +krasnoyarsk.ru +kuban.ru +kurgan.ru +kursk.ru +lipetsk.ru +magadan.ru +mari.ru +mari-el.ru +marine.ru +mordovia.ru +// mosreg.ru Bug 1090800 - removed at request of Aleksey Konstantinov +msk.ru +murmansk.ru +nalchik.ru +nnov.ru +nov.ru +novosibirsk.ru +nsk.ru +omsk.ru +orenburg.ru +oryol.ru +palana.ru +penza.ru +perm.ru +ptz.ru +rnd.ru +ryazan.ru +sakhalin.ru +samara.ru +saratov.ru +simbirsk.ru +smolensk.ru +spb.ru +stavropol.ru +stv.ru +surgut.ru +tambov.ru +tatarstan.ru +tom.ru +tomsk.ru +tsaritsyn.ru +tsk.ru +tula.ru +tuva.ru +tver.ru +tyumen.ru +udm.ru +udmurtia.ru +ulan-ude.ru +vladikavkaz.ru +vladimir.ru +vladivostok.ru +volgograd.ru +vologda.ru +voronezh.ru +vrn.ru +vyatka.ru +yakutia.ru +yamal.ru +yaroslavl.ru +yekaterinburg.ru +yuzhno-sakhalinsk.ru +// More geographical domains +amursk.ru +baikal.ru +cmw.ru +fareast.ru +jamal.ru +kms.ru +k-uralsk.ru +kustanai.ru +kuzbass.ru +mytis.ru +nakhodka.ru +nkz.ru +norilsk.ru +oskol.ru +pyatigorsk.ru +rubtsovsk.ru +snz.ru +syzran.ru +vdonsk.ru +zgrad.ru +// State domains +gov.ru +mil.ru +// Technical domains +test.ru + +// rw : http://www.nic.rw/cgi-bin/policy.pl +rw +gov.rw +net.rw +edu.rw +ac.rw +com.rw +co.rw +int.rw +mil.rw +gouv.rw + +// sa : http://www.nic.net.sa/ +sa +com.sa +net.sa +org.sa +gov.sa +med.sa +pub.sa +edu.sa +sch.sa + +// sb : http://www.sbnic.net.sb/ +// Submitted by registry +sb +com.sb +edu.sb +gov.sb +net.sb +org.sb + +// sc : http://www.nic.sc/ +sc +com.sc +gov.sc +net.sc +org.sc +edu.sc + +// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm +// Submitted by registry +sd +com.sd +net.sd +org.sd +edu.sd +med.sd +tv.sd +gov.sd +info.sd + +// se : https://en.wikipedia.org/wiki/.se +// Submitted by registry +se +a.se +ac.se +b.se +bd.se +brand.se +c.se +d.se +e.se +f.se +fh.se +fhsk.se +fhv.se +g.se +h.se +i.se +k.se +komforb.se +kommunalforbund.se +komvux.se +l.se +lanbib.se +m.se +n.se +naturbruksgymn.se +o.se +org.se +p.se +parti.se +pp.se +press.se +r.se +s.se +t.se +tm.se +u.se +w.se +x.se +y.se +z.se + +// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines +sg +com.sg +net.sg +org.sg +gov.sg +edu.sg +per.sg + +// sh : http://www.nic.sh/registrar.html +sh +com.sh +net.sh +gov.sh +org.sh +mil.sh + +// si : https://en.wikipedia.org/wiki/.si +si + +// sj : No registrations at this time. +// Submitted by registry +sj + +// sk : https://en.wikipedia.org/wiki/.sk +// list of 2nd level domains ? +sk + +// sl : http://www.nic.sl +// Submitted by registry +sl +com.sl +net.sl +edu.sl +gov.sl +org.sl + +// sm : https://en.wikipedia.org/wiki/.sm +sm + +// sn : https://en.wikipedia.org/wiki/.sn +sn +art.sn +com.sn +edu.sn +gouv.sn +org.sn +perso.sn +univ.sn + +// so : http://www.soregistry.com/ +so +com.so +net.so +org.so + +// sr : https://en.wikipedia.org/wiki/.sr +sr + +// st : http://www.nic.st/html/policyrules/ +st +co.st +com.st +consulado.st +edu.st +embaixada.st +gov.st +mil.st +net.st +org.st +principe.st +saotome.st +store.st + +// su : https://en.wikipedia.org/wiki/.su +su +adygeya.su +arkhangelsk.su +balashov.su +bashkiria.su +bryansk.su +dagestan.su +grozny.su +ivanovo.su +kalmykia.su +kaluga.su +karelia.su +khakassia.su +krasnodar.su +kurgan.su +lenug.su +mordovia.su +msk.su +murmansk.su +nalchik.su +nov.su +obninsk.su +penza.su +pokrovsk.su +sochi.su +spb.su +togliatti.su +troitsk.su +tula.su +tuva.su +vladikavkaz.su +vladimir.su +vologda.su + +// sv : http://www.svnet.org.sv/niveldos.pdf +sv +com.sv +edu.sv +gob.sv +org.sv +red.sv + +// sx : https://en.wikipedia.org/wiki/.sx +// Submitted by registry +sx +gov.sx + +// sy : https://en.wikipedia.org/wiki/.sy +// see also: http://www.gobin.info/domainname/sy.doc +sy +edu.sy +gov.sy +net.sy +mil.sy +com.sy +org.sy + +// sz : https://en.wikipedia.org/wiki/.sz +// http://www.sispa.org.sz/ +sz +co.sz +ac.sz +org.sz + +// tc : https://en.wikipedia.org/wiki/.tc +tc + +// td : https://en.wikipedia.org/wiki/.td +td + +// tel: https://en.wikipedia.org/wiki/.tel +// http://www.telnic.org/ +tel + +// tf : https://en.wikipedia.org/wiki/.tf +tf + +// tg : https://en.wikipedia.org/wiki/.tg +// http://www.nic.tg/ +tg + +// th : https://en.wikipedia.org/wiki/.th +// Submitted by registry +th +ac.th +co.th +go.th +in.th +mi.th +net.th +or.th + +// tj : http://www.nic.tj/policy.html +tj +ac.tj +biz.tj +co.tj +com.tj +edu.tj +go.tj +gov.tj +int.tj +mil.tj +name.tj +net.tj +nic.tj +org.tj +test.tj +web.tj + +// tk : https://en.wikipedia.org/wiki/.tk +tk + +// tl : https://en.wikipedia.org/wiki/.tl +tl +gov.tl + +// tm : http://www.nic.tm/local.html +tm +com.tm +co.tm +org.tm +net.tm +nom.tm +gov.tm +mil.tm +edu.tm + +// tn : https://en.wikipedia.org/wiki/.tn +// http://whois.ati.tn/ +tn +com.tn +ens.tn +fin.tn +gov.tn +ind.tn +intl.tn +nat.tn +net.tn +org.tn +info.tn +perso.tn +tourism.tn +edunet.tn +rnrt.tn +rns.tn +rnu.tn +mincom.tn +agrinet.tn +defense.tn +turen.tn + +// to : https://en.wikipedia.org/wiki/.to +// Submitted by registry +to +com.to +gov.to +net.to +org.to +edu.to +mil.to + +// subTLDs: https://www.nic.tr/forms/eng/policies.pdf +// and: https://www.nic.tr/forms/politikalar.pdf +// Submitted by +tr +com.tr +info.tr +biz.tr +net.tr +org.tr +web.tr +gen.tr +tv.tr +av.tr +dr.tr +bbs.tr +name.tr +tel.tr +gov.tr +bel.tr +pol.tr +mil.tr +k12.tr +edu.tr +kep.tr + +// Used by Northern Cyprus +nc.tr + +// Used by government agencies of Northern Cyprus +gov.nc.tr + +// travel : https://en.wikipedia.org/wiki/.travel +travel + +// tt : http://www.nic.tt/ +tt +co.tt +com.tt +org.tt +net.tt +biz.tt +info.tt +pro.tt +int.tt +coop.tt +jobs.tt +mobi.tt +travel.tt +museum.tt +aero.tt +name.tt +gov.tt +edu.tt + +// tv : https://en.wikipedia.org/wiki/.tv +// Not listing any 2LDs as reserved since none seem to exist in practice, +// Wikipedia notwithstanding. +tv + +// tw : https://en.wikipedia.org/wiki/.tw +tw +edu.tw +gov.tw +mil.tw +com.tw +net.tw +org.tw +idv.tw +game.tw +ebiz.tw +club.tw +網路.tw +組織.tw +商業.tw + +// tz : http://www.tznic.or.tz/index.php/domains +// Submitted by registry +tz +ac.tz +co.tz +go.tz +hotel.tz +info.tz +me.tz +mil.tz +mobi.tz +ne.tz +or.tz +sc.tz +tv.tz + +// ua : https://hostmaster.ua/policy/?ua +// Submitted by registry +ua +// ua 2LD +com.ua +edu.ua +gov.ua +in.ua +net.ua +org.ua +// ua geographic names +// https://hostmaster.ua/2ld/ +cherkassy.ua +cherkasy.ua +chernigov.ua +chernihiv.ua +chernivtsi.ua +chernovtsy.ua +ck.ua +cn.ua +cr.ua +crimea.ua +cv.ua +dn.ua +dnepropetrovsk.ua +dnipropetrovsk.ua +dominic.ua +donetsk.ua +dp.ua +if.ua +ivano-frankivsk.ua +kh.ua +kharkiv.ua +kharkov.ua +kherson.ua +khmelnitskiy.ua +khmelnytskyi.ua +kiev.ua +kirovograd.ua +km.ua +kr.ua +krym.ua +ks.ua +kv.ua +kyiv.ua +lg.ua +lt.ua +lugansk.ua +lutsk.ua +lv.ua +lviv.ua +mk.ua +mykolaiv.ua +nikolaev.ua +od.ua +odesa.ua +odessa.ua +pl.ua +poltava.ua +rivne.ua +rovno.ua +rv.ua +sb.ua +sebastopol.ua +sevastopol.ua +sm.ua +sumy.ua +te.ua +ternopil.ua +uz.ua +uzhgorod.ua +vinnica.ua +vinnytsia.ua +vn.ua +volyn.ua +yalta.ua +zaporizhzhe.ua +zaporizhzhia.ua +zhitomir.ua +zhytomyr.ua +zp.ua +zt.ua + +// ug : https://www.registry.co.ug/ +ug +co.ug +or.ug +ac.ug +sc.ug +go.ug +ne.ug +com.ug +org.ug + +// uk : https://en.wikipedia.org/wiki/.uk +// Submitted by registry +uk +ac.uk +co.uk +gov.uk +ltd.uk +me.uk +net.uk +nhs.uk +org.uk +plc.uk +police.uk +*.sch.uk + +// us : https://en.wikipedia.org/wiki/.us +us +dni.us +fed.us +isa.us +kids.us +nsn.us +// us geographic names +ak.us +al.us +ar.us +as.us +az.us +ca.us +co.us +ct.us +dc.us +de.us +fl.us +ga.us +gu.us +hi.us +ia.us +id.us +il.us +in.us +ks.us +ky.us +la.us +ma.us +md.us +me.us +mi.us +mn.us +mo.us +ms.us +mt.us +nc.us +nd.us +ne.us +nh.us +nj.us +nm.us +nv.us +ny.us +oh.us +ok.us +or.us +pa.us +pr.us +ri.us +sc.us +sd.us +tn.us +tx.us +ut.us +vi.us +vt.us +va.us +wa.us +wi.us +wv.us +wy.us +// The registrar notes several more specific domains available in each state, +// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat +// haphazard; in some states these domains resolve as addresses, while in others +// only subdomains are available, or even nothing at all. We include the +// most common ones where it's clear that different sites are different +// entities. +k12.ak.us +k12.al.us +k12.ar.us +k12.as.us +k12.az.us +k12.ca.us +k12.co.us +k12.ct.us +k12.dc.us +k12.de.us +k12.fl.us +k12.ga.us +k12.gu.us +// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login +k12.ia.us +k12.id.us +k12.il.us +k12.in.us +k12.ks.us +k12.ky.us +k12.la.us +k12.ma.us +k12.md.us +k12.me.us +k12.mi.us +k12.mn.us +k12.mo.us +k12.ms.us +k12.mt.us +k12.nc.us +// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso +k12.ne.us +k12.nh.us +k12.nj.us +k12.nm.us +k12.nv.us +k12.ny.us +k12.oh.us +k12.ok.us +k12.or.us +k12.pa.us +k12.pr.us +k12.ri.us +k12.sc.us +// k12.sd.us Bug 934131 - Removed at request of James Booze +k12.tn.us +k12.tx.us +k12.ut.us +k12.vi.us +k12.vt.us +k12.va.us +k12.wa.us +k12.wi.us +// k12.wv.us Bug 947705 - Removed at request of Verne Britton +k12.wy.us +cc.ak.us +cc.al.us +cc.ar.us +cc.as.us +cc.az.us +cc.ca.us +cc.co.us +cc.ct.us +cc.dc.us +cc.de.us +cc.fl.us +cc.ga.us +cc.gu.us +cc.hi.us +cc.ia.us +cc.id.us +cc.il.us +cc.in.us +cc.ks.us +cc.ky.us +cc.la.us +cc.ma.us +cc.md.us +cc.me.us +cc.mi.us +cc.mn.us +cc.mo.us +cc.ms.us +cc.mt.us +cc.nc.us +cc.nd.us +cc.ne.us +cc.nh.us +cc.nj.us +cc.nm.us +cc.nv.us +cc.ny.us +cc.oh.us +cc.ok.us +cc.or.us +cc.pa.us +cc.pr.us +cc.ri.us +cc.sc.us +cc.sd.us +cc.tn.us +cc.tx.us +cc.ut.us +cc.vi.us +cc.vt.us +cc.va.us +cc.wa.us +cc.wi.us +cc.wv.us +cc.wy.us +lib.ak.us +lib.al.us +lib.ar.us +lib.as.us +lib.az.us +lib.ca.us +lib.co.us +lib.ct.us +lib.dc.us +lib.de.us +lib.fl.us +lib.ga.us +lib.gu.us +lib.hi.us +lib.ia.us +lib.id.us +lib.il.us +lib.in.us +lib.ks.us +lib.ky.us +lib.la.us +lib.ma.us +lib.md.us +lib.me.us +lib.mi.us +lib.mn.us +lib.mo.us +lib.ms.us +lib.mt.us +lib.nc.us +lib.nd.us +lib.ne.us +lib.nh.us +lib.nj.us +lib.nm.us +lib.nv.us +lib.ny.us +lib.oh.us +lib.ok.us +lib.or.us +lib.pa.us +lib.pr.us +lib.ri.us +lib.sc.us +lib.sd.us +lib.tn.us +lib.tx.us +lib.ut.us +lib.vi.us +lib.vt.us +lib.va.us +lib.wa.us +lib.wi.us +// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold +lib.wy.us +// k12.ma.us contains school districts in Massachusetts. The 4LDs are +// managed independently except for private (PVT), charter (CHTR) and +// parochial (PAROCH) schools. Those are delegated directly to the +// 5LD operators. +pvt.k12.ma.us +chtr.k12.ma.us +paroch.k12.ma.us + +// uy : http://www.nic.org.uy/ +uy +com.uy +edu.uy +gub.uy +mil.uy +net.uy +org.uy + +// uz : http://www.reg.uz/ +uz +co.uz +com.uz +net.uz +org.uz + +// va : https://en.wikipedia.org/wiki/.va +va + +// vc : https://en.wikipedia.org/wiki/.vc +// Submitted by registry +vc +com.vc +net.vc +org.vc +gov.vc +mil.vc +edu.vc + +// ve : https://registro.nic.ve/ +// Submitted by registry +ve +arts.ve +co.ve +com.ve +e12.ve +edu.ve +firm.ve +gob.ve +gov.ve +info.ve +int.ve +mil.ve +net.ve +org.ve +rec.ve +store.ve +tec.ve +web.ve + +// vg : https://en.wikipedia.org/wiki/.vg +vg + +// vi : http://www.nic.vi/newdomainform.htm +// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other +// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they +// are available for registration (which they do not seem to be). +vi +co.vi +com.vi +k12.vi +net.vi +org.vi + +// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp +vn +com.vn +net.vn +org.vn +edu.vn +gov.vn +int.vn +ac.vn +biz.vn +info.vn +name.vn +pro.vn +health.vn + +// vu : https://en.wikipedia.org/wiki/.vu +// http://www.vunic.vu/ +vu +com.vu +edu.vu +net.vu +org.vu + +// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +wf + +// ws : https://en.wikipedia.org/wiki/.ws +// http://samoanic.ws/index.dhtml +ws +com.ws +net.ws +org.ws +gov.ws +edu.ws + +// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf +yt + +// IDN ccTLDs +// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then +// U-label, and follow this format: +// // A-Label ("", [, variant info]) : +// // [sponsoring org] +// U-Label + +// xn--mgbaam7a8h ("Emerat", Arabic) : AE +// http://nic.ae/english/arabicdomain/rules.jsp +امارات + +// xn--y9a3aq ("hye", Armenian) : AM +// ISOC AM (operated by .am Registry) +հայ + +// xn--54b7fta0cc ("Bangla", Bangla) : BD +বাংলা + +// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY +// Operated by .by registry +бел + +// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中国 + +// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中國 + +// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ +الجزائر + +// xn--wgbh1c ("Egypt/Masr", Arabic) : EG +// http://www.dotmasr.eg/ +مصر + +// xn--e1a4c ("eu", Cyrillic) : EU +ею + +// xn--node ("ge", Georgian Mkhedruli) : GE +გე + +// xn--qxam ("el", Greek) : GR +// Hellenic Ministry of Infrastructure, Transport, and Networks +ελ + +// xn--j6w193g ("Hong Kong", Chinese) : HK +// https://www2.hkirc.hk/register/rules.jsp +香港 + +// xn--h2brj9c ("Bharat", Devanagari) : IN +// India +भारत + +// xn--mgbbh1a71e ("Bharat", Arabic) : IN +// India +بھارت + +// xn--fpcrj9c3d ("Bharat", Telugu) : IN +// India +భారత్ + +// xn--gecrj9c ("Bharat", Gujarati) : IN +// India +ભારત + +// xn--s9brj9c ("Bharat", Gurmukhi) : IN +// India +ਭਾਰਤ + +// xn--45brj9c ("Bharat", Bengali) : IN +// India +ভারত + +// xn--xkc2dl3a5ee0h ("India", Tamil) : IN +// India +இந்தியா + +// xn--mgba3a4f16a ("Iran", Persian) : IR +ایران + +// xn--mgba3a4fra ("Iran", Arabic) : IR +ايران + +// xn--mgbtx2b ("Iraq", Arabic) : IQ +// Communications and Media Commission +عراق + +// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO +// National Information Technology Center (NITC) +// Royal Scientific Society, Al-Jubeiha +الاردن + +// xn--3e0b707e ("Republic of Korea", Hangul) : KR +한국 + +// xn--80ao21a ("Kaz", Kazakh) : KZ +қаз + +// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK +// http://nic.lk +ලංකා + +// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK +// http://nic.lk +இலங்கை + +// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA +المغرب + +// xn--d1alf ("mkd", Macedonian) : MK +// MARnet +мкд + +// xn--l1acc ("mon", Mongolian) : MN +мон + +// xn--mix891f ("Macao", Chinese, Traditional) : MO +// MONIC / HNET Asia (Registry Operator for .mo) +澳門 + +// xn--mix082f ("Macao", Chinese, Simplified) : MO +澳门 + +// xn--mgbx4cd0ab ("Malaysia", Malay) : MY +مليسيا + +// xn--mgb9awbf ("Oman", Arabic) : OM +عمان + +// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK +پاکستان + +// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK +پاكستان + +// xn--ygbi2ammx ("Falasteen", Arabic) : PS +// The Palestinian National Internet Naming Authority (PNINA) +// http://www.pnina.ps +فلسطين + +// xn--90a3ac ("srb", Cyrillic) : RS +// https://www.rnids.rs/en/domains/national-domains +срб +пр.срб +орг.срб +обр.срб +од.срб +упр.срб +ак.срб + +// xn--p1ai ("rf", Russian-Cyrillic) : RU +// http://www.cctld.ru/en/docs/rulesrf.php +рф + +// xn--wgbl6a ("Qatar", Arabic) : QA +// http://www.ict.gov.qa/ +قطر + +// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA +// http://www.nic.net.sa/ +السعودية + +// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA +السعودیة + +// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA +السعودیۃ + +// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA +السعوديه + +// xn--mgbpl2fh ("sudan", Arabic) : SD +// Operated by .sd registry +سودان + +// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG +新加坡 + +// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG +சிங்கப்பூர் + +// xn--ogbpf8fl ("Syria", Arabic) : SY +سورية + +// xn--mgbtf8fl ("Syria", Arabic, variant) : SY +سوريا + +// xn--o3cw4h ("Thai", Thai) : TH +// http://www.thnic.co.th +ไทย + +// xn--pgbs0dh ("Tunisia", Arabic) : TN +// http://nic.tn +تونس + +// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台灣 + +// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台湾 + +// xn--nnx388a ("Taiwan", Chinese, variant) : TW +臺灣 + +// xn--j1amh ("ukr", Cyrillic) : UA +укр + +// xn--mgb2ddes ("AlYemen", Arabic) : YE +اليمن + +// xxx : http://icmregistry.com +xxx + +// ye : http://www.y.net.ye/services/domain_name.htm +*.ye + +// za : http://www.zadna.org.za/content/page/domain-information +ac.za +agric.za +alt.za +co.za +edu.za +gov.za +grondar.za +law.za +mil.za +net.za +ngo.za +nis.za +nom.za +org.za +school.za +tm.za +web.za + +// zm : https://zicta.zm/ +// Submitted by registry +zm +ac.zm +biz.zm +co.zm +com.zm +edu.zm +gov.zm +info.zm +mil.zm +net.zm +org.zm +sch.zm + +// zw : https://en.wikipedia.org/wiki/.zw +*.zw + + +// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2016-05-09T22:17:27Z + +// aaa : 2015-02-26 American Automobile Association, Inc. +aaa + +// aarp : 2015-05-21 AARP +aarp + +// abarth : 2015-07-30 Fiat Chrysler Automobiles N.V. +abarth + +// abb : 2014-10-24 ABB Ltd +abb + +// abbott : 2014-07-24 Abbott Laboratories, Inc. +abbott + +// abbvie : 2015-07-30 AbbVie Inc. +abbvie + +// abc : 2015-07-30 Disney Enterprises, Inc. +abc + +// able : 2015-06-25 Able Inc. +able + +// abogado : 2014-04-24 Top Level Domain Holdings Limited +abogado + +// abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre +abudhabi + +// academy : 2013-11-07 Half Oaks, LLC +academy + +// accenture : 2014-08-15 Accenture plc +accenture + +// accountant : 2014-11-20 dot Accountant Limited +accountant + +// accountants : 2014-03-20 Knob Town, LLC +accountants + +// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG +aco + +// active : 2014-05-01 The Active Network, Inc +active + +// actor : 2013-12-12 United TLD Holdco Ltd. +actor + +// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC) +adac + +// ads : 2014-12-04 Charleston Road Registry Inc. +ads + +// adult : 2014-10-16 ICM Registry AD LLC +adult + +// aeg : 2015-03-19 Aktiebolaget Electrolux +aeg + +// aetna : 2015-05-21 Aetna Life Insurance Company +aetna + +// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc. +afamilycompany + +// afl : 2014-10-02 Australian Football League +afl + +// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa +africa + +// africamagic : 2015-03-05 Electronic Media Network (Pty) Ltd +africamagic + +// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) +agakhan + +// agency : 2013-11-14 Steel Falls, LLC +agency + +// aig : 2014-12-18 American International Group, Inc. +aig + +// aigo : 2015-08-06 aigo Digital Technology Co,Ltd. +aigo + +// airbus : 2015-07-30 Airbus S.A.S. +airbus + +// airforce : 2014-03-06 United TLD Holdco Ltd. +airforce + +// airtel : 2014-10-24 Bharti Airtel Limited +airtel + +// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) +akdn + +// alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V. +alfaromeo + +// alibaba : 2015-01-15 Alibaba Group Holding Limited +alibaba + +// alipay : 2015-01-15 Alibaba Group Holding Limited +alipay + +// allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft +allfinanz + +// allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company +allstate + +// ally : 2015-06-18 Ally Financial Inc. +ally + +// alsace : 2014-07-02 REGION D ALSACE +alsace + +// alstom : 2015-07-30 ALSTOM +alstom + +// americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc. +americanexpress + +// americanfamily : 2015-07-23 AmFam, Inc. +americanfamily + +// amex : 2015-07-31 American Express Travel Related Services Company, Inc. +amex + +// amfam : 2015-07-23 AmFam, Inc. +amfam + +// amica : 2015-05-28 Amica Mutual Insurance Company +amica + +// amsterdam : 2014-07-24 Gemeente Amsterdam +amsterdam + +// analytics : 2014-12-18 Campus IP LLC +analytics + +// android : 2014-08-07 Charleston Road Registry Inc. +android + +// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +anquan + +// anz : 2015-07-31 Australia and New Zealand Banking Group Limited +anz + +// aol : 2015-09-17 AOL Inc. +aol + +// apartments : 2014-12-11 June Maple, LLC +apartments + +// app : 2015-05-14 Charleston Road Registry Inc. +app + +// apple : 2015-05-14 Apple Inc. +apple + +// aquarelle : 2014-07-24 Aquarelle.com +aquarelle + +// arab : 2015-11-12 League of Arab States +arab + +// aramco : 2014-11-20 Aramco Services Company +aramco + +// archi : 2014-02-06 STARTING DOT LIMITED +archi + +// army : 2014-03-06 United TLD Holdco Ltd. +army + +// art : 2016-03-24 UK Creative Ideas Limited +art + +// arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E. +arte + +// asda : 2015-07-31 Wal-Mart Stores, Inc. +asda + +// associates : 2014-03-06 Baxter Hill, LLC +associates + +// athleta : 2015-07-30 The Gap, Inc. +athleta + +// attorney : 2014-03-20 +attorney + +// auction : 2014-03-20 +auction + +// audi : 2015-05-21 AUDI Aktiengesellschaft +audi + +// audible : 2015-06-25 Amazon EU S.à r.l. +audible + +// audio : 2014-03-20 Uniregistry, Corp. +audio + +// auspost : 2015-08-13 Australian Postal Corporation +auspost + +// author : 2014-12-18 Amazon EU S.à r.l. +author + +// auto : 2014-11-13 +auto + +// autos : 2014-01-09 DERAutos, LLC +autos + +// avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca +avianca + +// aws : 2015-06-25 Amazon EU S.à r.l. +aws + +// axa : 2013-12-19 AXA SA +axa + +// azure : 2014-12-18 Microsoft Corporation +azure + +// baby : 2015-04-09 Johnson & Johnson Services, Inc. +baby + +// baidu : 2015-01-08 Baidu, Inc. +baidu + +// banamex : 2015-07-30 Citigroup Inc. +banamex + +// bananarepublic : 2015-07-31 The Gap, Inc. +bananarepublic + +// band : 2014-06-12 +band + +// bank : 2014-09-25 fTLD Registry Services LLC +bank + +// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +bar + +// barcelona : 2014-07-24 Municipi de Barcelona +barcelona + +// barclaycard : 2014-11-20 Barclays Bank PLC +barclaycard + +// barclays : 2014-11-20 Barclays Bank PLC +barclays + +// barefoot : 2015-06-11 Gallo Vineyards, Inc. +barefoot + +// bargains : 2013-11-14 Half Hallow, LLC +bargains + +// baseball : 2015-10-29 MLB Advanced Media DH, LLC +baseball + +// basketball : 2015-08-20 Fédération Internationale de Basketball (FIBA) +basketball + +// bauhaus : 2014-04-17 Werkhaus GmbH +bauhaus + +// bayern : 2014-01-23 Bayern Connect GmbH +bayern + +// bbc : 2014-12-18 British Broadcasting Corporation +bbc + +// bbt : 2015-07-23 BB&T Corporation +bbt + +// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A. +bbva + +// bcg : 2015-04-02 The Boston Consulting Group, Inc. +bcg + +// bcn : 2014-07-24 Municipi de Barcelona +bcn + +// beats : 2015-05-14 Beats Electronics, LLC +beats + +// beauty : 2015-12-03 L'Oréal +beauty + +// beer : 2014-01-09 Top Level Domain Holdings Limited +beer + +// bentley : 2014-12-18 Bentley Motors Limited +bentley + +// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG +berlin + +// best : 2013-12-19 BestTLD Pty Ltd +best + +// bestbuy : 2015-07-31 BBY Solutions, Inc. +bestbuy + +// bet : 2015-05-07 Afilias plc +bet + +// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited +bharti + +// bible : 2014-06-19 American Bible Society +bible + +// bid : 2013-12-19 dot Bid Limited +bid + +// bike : 2013-08-27 Grand Hollow, LLC +bike + +// bing : 2014-12-18 Microsoft Corporation +bing + +// bingo : 2014-12-04 Sand Cedar, LLC +bingo + +// bio : 2014-03-06 STARTING DOT LIMITED +bio + +// black : 2014-01-16 Afilias Limited +black + +// blackfriday : 2014-01-16 Uniregistry, Corp. +blackfriday + +// blanco : 2015-07-16 BLANCO GmbH + Co KG +blanco + +// blockbuster : 2015-07-30 Dish DBS Corporation +blockbuster + +// blog : 2015-05-14 PRIMER NIVEL S.A. +blog + +// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC +bloomberg + +// blue : 2013-11-07 Afilias Limited +blue + +// bms : 2014-10-30 Bristol-Myers Squibb Company +bms + +// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +bmw + +// bnl : 2014-07-24 Banca Nazionale del Lavoro +bnl + +// bnpparibas : 2014-05-29 BNP Paribas +bnpparibas + +// boats : 2014-12-04 DERBoats, LLC +boats + +// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH +boehringer + +// bofa : 2015-07-31 NMS Services, Inc. +bofa + +// bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +bom + +// bond : 2014-06-05 Bond University Limited +bond + +// boo : 2014-01-30 Charleston Road Registry Inc. +boo + +// book : 2015-08-27 Amazon EU S.à r.l. +book + +// booking : 2015-07-16 Booking.com B.V. +booking + +// boots : 2015-01-08 THE BOOTS COMPANY PLC +boots + +// bosch : 2015-06-18 Robert Bosch GMBH +bosch + +// bostik : 2015-05-28 Bostik SA +bostik + +// boston : 2015-12-10 Boston Globe Media Partners, LLC +boston + +// bot : 2014-12-18 Amazon EU S.à r.l. +bot + +// boutique : 2013-11-14 Over Galley, LLC +boutique + +// box : 2015-11-12 NS1 Limited +box + +// bradesco : 2014-12-18 Banco Bradesco S.A. +bradesco + +// bridgestone : 2014-12-18 Bridgestone Corporation +bridgestone + +// broadway : 2014-12-22 Celebrate Broadway, Inc. +broadway + +// broker : 2014-12-11 IG Group Holdings PLC +broker + +// brother : 2015-01-29 Brother Industries, Ltd. +brother + +// brussels : 2014-02-06 DNS.be vzw +brussels + +// budapest : 2013-11-21 Top Level Domain Holdings Limited +budapest + +// bugatti : 2015-07-23 Bugatti International SA +bugatti + +// build : 2013-11-07 Plan Bee LLC +build + +// builders : 2013-11-07 Atomic Madison, LLC +builders + +// business : 2013-11-07 Spring Cross, LLC +business + +// buy : 2014-12-18 Amazon EU S.à r.l. +buy + +// buzz : 2013-10-02 DOTSTRATEGY CO. +buzz + +// bzh : 2014-02-27 Association www.bzh +bzh + +// cab : 2013-10-24 Half Sunset, LLC +cab + +// cafe : 2015-02-11 Pioneer Canyon, LLC +cafe + +// cal : 2014-07-24 Charleston Road Registry Inc. +cal + +// call : 2014-12-18 Amazon EU S.à r.l. +call + +// calvinklein : 2015-07-30 PVH gTLD Holdings LLC +calvinklein + +// cam : 2016-04-21 AC Webconnecting Holding B.V. +cam + +// camera : 2013-08-27 Atomic Maple, LLC +camera + +// camp : 2013-11-07 Delta Dynamite, LLC +camp + +// cancerresearch : 2014-05-15 Australian Cancer Research Foundation +cancerresearch + +// canon : 2014-09-12 Canon Inc. +canon + +// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +capetown + +// capital : 2014-03-06 Delta Mill, LLC +capital + +// capitalone : 2015-08-06 Capital One Financial Corporation +capitalone + +// car : 2015-01-22 +car + +// caravan : 2013-12-12 Caravan International, Inc. +caravan + +// cards : 2013-12-05 Foggy Hollow, LLC +cards + +// care : 2014-03-06 Goose Cross +care + +// career : 2013-10-09 dotCareer LLC +career + +// careers : 2013-10-02 Wild Corner, LLC +careers + +// cars : 2014-11-13 +cars + +// cartier : 2014-06-23 Richemont DNS Inc. +cartier + +// casa : 2013-11-21 Top Level Domain Holdings Limited +casa + +// case : 2015-09-03 CNH Industrial N.V. +case + +// caseih : 2015-09-03 CNH Industrial N.V. +caseih + +// cash : 2014-03-06 Delta Lake, LLC +cash + +// casino : 2014-12-18 Binky Sky, LLC +casino + +// catering : 2013-12-05 New Falls. LLC +catering + +// catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +catholic + +// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +cba + +// cbn : 2014-08-22 The Christian Broadcasting Network, Inc. +cbn + +// cbre : 2015-07-02 CBRE, Inc. +cbre + +// cbs : 2015-08-06 CBS Domains Inc. +cbs + +// ceb : 2015-04-09 The Corporate Executive Board Company +ceb + +// center : 2013-11-07 Tin Mill, LLC +center + +// ceo : 2013-11-07 CEOTLD Pty Ltd +ceo + +// cern : 2014-06-05 European Organization for Nuclear Research ("CERN") +cern + +// cfa : 2014-08-28 CFA Institute +cfa + +// cfd : 2014-12-11 IG Group Holdings PLC +cfd + +// chanel : 2015-04-09 Chanel International B.V. +chanel + +// channel : 2014-05-08 Charleston Road Registry Inc. +channel + +// chase : 2015-04-30 JPMorgan Chase & Co. +chase + +// chat : 2014-12-04 Sand Fields, LLC +chat + +// cheap : 2013-11-14 Sand Cover, LLC +cheap + +// chintai : 2015-06-11 CHINTAI Corporation +chintai + +// chloe : 2014-10-16 Richemont DNS Inc. +chloe + +// christmas : 2013-11-21 Uniregistry, Corp. +christmas + +// chrome : 2014-07-24 Charleston Road Registry Inc. +chrome + +// chrysler : 2015-07-30 FCA US LLC. +chrysler + +// church : 2014-02-06 Holly Fields, LLC +church + +// cipriani : 2015-02-19 Hotel Cipriani Srl +cipriani + +// circle : 2014-12-18 Amazon EU S.à r.l. +circle + +// cisco : 2014-12-22 Cisco Technology, Inc. +cisco + +// citadel : 2015-07-23 Citadel Domain LLC +citadel + +// citi : 2015-07-30 Citigroup Inc. +citi + +// citic : 2014-01-09 CITIC Group Corporation +citic + +// city : 2014-05-29 Snow Sky, LLC +city + +// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc. +cityeats + +// claims : 2014-03-20 Black Corner, LLC +claims + +// cleaning : 2013-12-05 Fox Shadow, LLC +cleaning + +// click : 2014-06-05 Uniregistry, Corp. +click + +// clinic : 2014-03-20 Goose Park, LLC +clinic + +// clinique : 2015-10-01 The Estée Lauder Companies Inc. +clinique + +// clothing : 2013-08-27 Steel Lake, LLC +clothing + +// cloud : 2015-04-16 ARUBA S.p.A. +cloud + +// club : 2013-11-08 .CLUB DOMAINS, LLC +club + +// clubmed : 2015-06-25 Club Méditerranée S.A. +clubmed + +// coach : 2014-10-09 Koko Island, LLC +coach + +// codes : 2013-10-31 Puff Willow, LLC +codes + +// coffee : 2013-10-17 Trixy Cover, LLC +coffee + +// college : 2014-01-16 XYZ.COM LLC +college + +// cologne : 2014-02-05 NetCologne Gesellschaft für Telekommunikation mbH +cologne + +// comcast : 2015-07-23 Comcast IP Holdings I, LLC +comcast + +// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +commbank + +// community : 2013-12-05 Fox Orchard, LLC +community + +// company : 2013-11-07 Silver Avenue, LLC +company + +// compare : 2015-10-08 iSelect Ltd +compare + +// computer : 2013-10-24 Pine Mill, LLC +computer + +// comsec : 2015-01-08 VeriSign, Inc. +comsec + +// condos : 2013-12-05 Pine House, LLC +condos + +// construction : 2013-09-16 Fox Dynamite, LLC +construction + +// consulting : 2013-12-05 +consulting + +// contact : 2015-01-08 Top Level Spectrum, Inc. +contact + +// contractors : 2013-09-10 Magic Woods, LLC +contractors + +// cooking : 2013-11-21 Top Level Domain Holdings Limited +cooking + +// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. +cookingchannel + +// cool : 2013-11-14 Koko Lake, LLC +cool + +// corsica : 2014-09-25 Collectivité Territoriale de Corse +corsica + +// country : 2013-12-19 Top Level Domain Holdings Limited +country + +// coupon : 2015-02-26 Amazon EU S.à r.l. +coupon + +// coupons : 2015-03-26 Black Island, LLC +coupons + +// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD +courses + +// credit : 2014-03-20 Snow Shadow, LLC +credit + +// creditcard : 2014-03-20 Binky Frostbite, LLC +creditcard + +// creditunion : 2015-01-22 CUNA Performance Resources, LLC +creditunion + +// cricket : 2014-10-09 dot Cricket Limited +cricket + +// crown : 2014-10-24 Crown Equipment Corporation +crown + +// crs : 2014-04-03 Federated Co-operatives Limited +crs + +// cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd. +cruise + +// cruises : 2013-12-05 Spring Way, LLC +cruises + +// csc : 2014-09-25 Alliance-One Services, Inc. +csc + +// cuisinella : 2014-04-03 SALM S.A.S. +cuisinella + +// cymru : 2014-05-08 Nominet UK +cymru + +// cyou : 2015-01-22 Beijing Gamease Age Digital Technology Co., Ltd. +cyou + +// dabur : 2014-02-06 Dabur India Limited +dabur + +// dad : 2014-01-23 Charleston Road Registry Inc. +dad + +// dance : 2013-10-24 United TLD Holdco Ltd. +dance + +// date : 2014-11-20 dot Date Limited +date + +// dating : 2013-12-05 Pine Fest, LLC +dating + +// datsun : 2014-03-27 NISSAN MOTOR CO., LTD. +datsun + +// day : 2014-01-30 Charleston Road Registry Inc. +day + +// dclk : 2014-11-20 Charleston Road Registry Inc. +dclk + +// dds : 2015-05-07 Top Level Domain Holdings Limited +dds + +// deal : 2015-06-25 Amazon EU S.à r.l. +deal + +// dealer : 2014-12-22 Dealer Dot Com, Inc. +dealer + +// deals : 2014-05-22 Sand Sunset, LLC +deals + +// degree : 2014-03-06 +degree + +// delivery : 2014-09-11 Steel Station, LLC +delivery + +// dell : 2014-10-24 Dell Inc. +dell + +// deloitte : 2015-07-31 Deloitte Touche Tohmatsu +deloitte + +// delta : 2015-02-19 Delta Air Lines, Inc. +delta + +// democrat : 2013-10-24 United TLD Holdco Ltd. +democrat + +// dental : 2014-03-20 Tin Birch, LLC +dental + +// dentist : 2014-03-20 +dentist + +// desi : 2013-11-14 Desi Networks LLC +desi + +// design : 2014-11-07 Top Level Design, LLC +design + +// dev : 2014-10-16 Charleston Road Registry Inc. +dev + +// dhl : 2015-07-23 Deutsche Post AG +dhl + +// diamonds : 2013-09-22 John Edge, LLC +diamonds + +// diet : 2014-06-26 Uniregistry, Corp. +diet + +// digital : 2014-03-06 Dash Park, LLC +digital + +// direct : 2014-04-10 Half Trail, LLC +direct + +// directory : 2013-09-20 Extra Madison, LLC +directory + +// discount : 2014-03-06 Holly Hill, LLC +discount + +// discover : 2015-07-23 Discover Financial Services +discover + +// dish : 2015-07-30 Dish DBS Corporation +dish + +// diy : 2015-11-05 Lifestyle Domain Holdings, Inc. +diy + +// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd. +dnp + +// docs : 2014-10-16 Charleston Road Registry Inc. +docs + +// dodge : 2015-07-30 FCA US LLC. +dodge + +// dog : 2014-12-04 Koko Mill, LLC +dog + +// doha : 2014-09-18 Communications Regulatory Authority (CRA) +doha + +// domains : 2013-10-17 Sugar Cross, LLC +domains + +// dot : 2015-05-21 Dish DBS Corporation +dot + +// download : 2014-11-20 dot Support Limited +download + +// drive : 2015-03-05 Charleston Road Registry Inc. +drive + +// dstv : 2015-03-12 MultiChoice (Proprietary) Limited +dstv + +// dtv : 2015-06-04 Dish DBS Corporation +dtv + +// dubai : 2015-01-01 Dubai Smart Government Department +dubai + +// duck : 2015-07-23 Johnson Shareholdings, Inc. +duck + +// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company +dunlop + +// duns : 2015-08-06 The Dun & Bradstreet Corporation +duns + +// dupont : 2015-06-25 E. I. du Pont de Nemours and Company +dupont + +// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +durban + +// dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +dvag + +// dwg : 2015-07-23 Autodesk, Inc. +dwg + +// earth : 2014-12-04 Interlink Co., Ltd. +earth + +// eat : 2014-01-23 Charleston Road Registry Inc. +eat + +// edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V. +edeka + +// education : 2013-11-07 Brice Way, LLC +education + +// email : 2013-10-31 Spring Madison, LLC +email + +// emerck : 2014-04-03 Merck KGaA +emerck + +// emerson : 2015-07-23 Emerson Electric Co. +emerson + +// energy : 2014-09-11 Binky Birch, LLC +energy + +// engineer : 2014-03-06 United TLD Holdco Ltd. +engineer + +// engineering : 2014-03-06 Romeo Canyon +engineering + +// enterprises : 2013-09-20 Snow Oaks, LLC +enterprises + +// epost : 2015-07-23 Deutsche Post AG +epost + +// epson : 2014-12-04 Seiko Epson Corporation +epson + +// equipment : 2013-08-27 Corn Station, LLC +equipment + +// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson +ericsson + +// erni : 2014-04-03 ERNI Group Holding AG +erni + +// esq : 2014-05-08 Charleston Road Registry Inc. +esq + +// estate : 2013-08-27 Trixy Park, LLC +estate + +// esurance : 2015-07-23 Esurance Insurance Company +esurance + +// etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) +etisalat + +// eurovision : 2014-04-24 European Broadcasting Union (EBU) +eurovision + +// eus : 2013-12-12 Puntueus Fundazioa +eus + +// events : 2013-12-05 Pioneer Maple, LLC +events + +// everbank : 2014-05-15 EverBank +everbank + +// exchange : 2014-03-06 Spring Falls, LLC +exchange + +// expert : 2013-11-21 Magic Pass, LLC +expert + +// exposed : 2013-12-05 Victor Beach, LLC +exposed + +// express : 2015-02-11 Sea Sunset, LLC +express + +// extraspace : 2015-05-14 Extra Space Storage LLC +extraspace + +// fage : 2014-12-18 Fage International S.A. +fage + +// fail : 2014-03-06 Atomic Pipe, LLC +fail + +// fairwinds : 2014-11-13 FairWinds Partners, LLC +fairwinds + +// faith : 2014-11-20 dot Faith Limited +faith + +// family : 2015-04-02 +family + +// fan : 2014-03-06 +fan + +// fans : 2014-11-07 Asiamix Digital Limited +fans + +// farm : 2013-11-07 Just Maple, LLC +farm + +// farmers : 2015-07-09 Farmers Insurance Exchange +farmers + +// fashion : 2014-07-03 Top Level Domain Holdings Limited +fashion + +// fast : 2014-12-18 Amazon EU S.à r.l. +fast + +// fedex : 2015-08-06 Federal Express Corporation +fedex + +// feedback : 2013-12-19 Top Level Spectrum, Inc. +feedback + +// ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V. +ferrari + +// ferrero : 2014-12-18 Ferrero Trading Lux S.A. +ferrero + +// fiat : 2015-07-31 Fiat Chrysler Automobiles N.V. +fiat + +// fidelity : 2015-07-30 Fidelity Brokerage Services LLC +fidelity + +// fido : 2015-08-06 Rogers Communications Partnership +fido + +// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd +film + +// final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br +final + +// finance : 2014-03-20 Cotton Cypress, LLC +finance + +// financial : 2014-03-06 Just Cover, LLC +financial + +// fire : 2015-06-25 Amazon EU S.à r.l. +fire + +// firestone : 2014-12-18 Bridgestone Corporation +firestone + +// firmdale : 2014-03-27 Firmdale Holdings Limited +firmdale + +// fish : 2013-12-12 Fox Woods, LLC +fish + +// fishing : 2013-11-21 Top Level Domain Holdings Limited +fishing + +// fit : 2014-11-07 Top Level Domain Holdings Limited +fit + +// fitness : 2014-03-06 Brice Orchard, LLC +fitness + +// flickr : 2015-04-02 Yahoo! Domain Services Inc. +flickr + +// flights : 2013-12-05 Fox Station, LLC +flights + +// flir : 2015-07-23 FLIR Systems, Inc. +flir + +// florist : 2013-11-07 Half Cypress, LLC +florist + +// flowers : 2014-10-09 Uniregistry, Corp. +flowers + +// flsmidth : 2014-07-24 FLSmidth A/S +flsmidth + +// fly : 2014-05-08 Charleston Road Registry Inc. +fly + +// foo : 2014-01-23 Charleston Road Registry Inc. +foo + +// food : 2016-04-21 Lifestyle Domain Holdings, Inc. +food + +// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc. +foodnetwork + +// football : 2014-12-18 Foggy Farms, LLC +football + +// ford : 2014-11-13 Ford Motor Company +ford + +// forex : 2014-12-11 IG Group Holdings PLC +forex + +// forsale : 2014-05-22 +forsale + +// forum : 2015-04-02 Fegistry, LLC +forum + +// foundation : 2013-12-05 John Dale, LLC +foundation + +// fox : 2015-09-11 FOX Registry, LLC +fox + +// free : 2015-12-10 Amazon EU S.à r.l. +free + +// fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH +fresenius + +// frl : 2014-05-15 FRLregistry B.V. +frl + +// frogans : 2013-12-19 OP3FT +frogans + +// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc. +frontdoor + +// frontier : 2015-02-05 Frontier Communications Corporation +frontier + +// ftr : 2015-07-16 Frontier Communications Corporation +ftr + +// fujitsu : 2015-07-30 Fujitsu Limited +fujitsu + +// fujixerox : 2015-07-23 Xerox DNHC LLC +fujixerox + +// fun : 2016-01-14 Oriental Trading Company, Inc. +fun + +// fund : 2014-03-20 John Castle, LLC +fund + +// furniture : 2014-03-20 Lone Fields, LLC +furniture + +// futbol : 2013-09-20 +futbol + +// fyi : 2015-04-02 Silver Tigers, LLC +fyi + +// gal : 2013-11-07 Asociación puntoGAL +gal + +// gallery : 2013-09-13 Sugar House, LLC +gallery + +// gallo : 2015-06-11 Gallo Vineyards, Inc. +gallo + +// gallup : 2015-02-19 Gallup, Inc. +gallup + +// game : 2015-05-28 Uniregistry, Corp. +game + +// games : 2015-05-28 Foggy Beach, LLC +games + +// gap : 2015-07-31 The Gap, Inc. +gap + +// garden : 2014-06-26 Top Level Domain Holdings Limited +garden + +// gbiz : 2014-07-17 Charleston Road Registry Inc. +gbiz + +// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems" +gdn + +// gea : 2014-12-04 GEA Group Aktiengesellschaft +gea + +// gent : 2014-01-23 COMBELL GROUP NV/SA +gent + +// genting : 2015-03-12 Resorts World Inc Pte. Ltd. +genting + +// george : 2015-07-31 Wal-Mart Stores, Inc. +george + +// ggee : 2014-01-09 GMO Internet, Inc. +ggee + +// gift : 2013-10-17 Uniregistry, Corp. +gift + +// gifts : 2014-07-03 Goose Sky, LLC +gifts + +// gives : 2014-03-06 United TLD Holdco Ltd. +gives + +// giving : 2014-11-13 Giving Limited +giving + +// glade : 2015-07-23 Johnson Shareholdings, Inc. +glade + +// glass : 2013-11-07 Black Cover, LLC +glass + +// gle : 2014-07-24 Charleston Road Registry Inc. +gle + +// global : 2014-04-17 Dot GLOBAL AS +global + +// globo : 2013-12-19 Globo Comunicação e Participações S.A +globo + +// gmail : 2014-05-01 Charleston Road Registry Inc. +gmail + +// gmbh : 2016-01-29 Extra Dynamite, LLC +gmbh + +// gmo : 2014-01-09 GMO Internet, Inc. +gmo + +// gmx : 2014-04-24 1&1 Mail & Media GmbH +gmx + +// godaddy : 2015-07-23 Go Daddy East, LLC +godaddy + +// gold : 2015-01-22 June Edge, LLC +gold + +// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD. +goldpoint + +// golf : 2014-12-18 Lone falls, LLC +golf + +// goo : 2014-12-18 NTT Resonant Inc. +goo + +// goodhands : 2015-07-31 Allstate Fire and Casualty Insurance Company +goodhands + +// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company +goodyear + +// goog : 2014-11-20 Charleston Road Registry Inc. +goog + +// google : 2014-07-24 Charleston Road Registry Inc. +google + +// gop : 2014-01-16 Republican State Leadership Committee, Inc. +gop + +// got : 2014-12-18 Amazon EU S.à r.l. +got + +// gotv : 2015-03-12 MultiChoice (Proprietary) Limited +gotv + +// grainger : 2015-05-07 Grainger Registry Services, LLC +grainger + +// graphics : 2013-09-13 Over Madison, LLC +graphics + +// gratis : 2014-03-20 Pioneer Tigers, LLC +gratis + +// green : 2014-05-08 Afilias Limited +green + +// gripe : 2014-03-06 Corn Sunset, LLC +gripe + +// group : 2014-08-15 Romeo Town, LLC +group + +// guardian : 2015-07-30 The Guardian Life Insurance Company of America +guardian + +// gucci : 2014-11-13 Guccio Gucci S.p.a. +gucci + +// guge : 2014-08-28 Charleston Road Registry Inc. +guge + +// guide : 2013-09-13 Snow Moon, LLC +guide + +// guitars : 2013-11-14 Uniregistry, Corp. +guitars + +// guru : 2013-08-27 Pioneer Cypress, LLC +guru + +// hair : 2015-12-03 L'Oréal +hair + +// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH +hamburg + +// hangout : 2014-11-13 Charleston Road Registry Inc. +hangout + +// haus : 2013-12-05 +haus + +// hbo : 2015-07-30 HBO Registry Services, Inc. +hbo + +// hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED +hdfc + +// hdfcbank : 2015-02-12 HDFC Bank Limited +hdfcbank + +// health : 2015-02-11 DotHealth, LLC +health + +// healthcare : 2014-06-12 Silver Glen, LLC +healthcare + +// help : 2014-06-26 Uniregistry, Corp. +help + +// helsinki : 2015-02-05 City of Helsinki +helsinki + +// here : 2014-02-06 Charleston Road Registry Inc. +here + +// hermes : 2014-07-10 HERMES INTERNATIONAL +hermes + +// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. +hgtv + +// hiphop : 2014-03-06 Uniregistry, Corp. +hiphop + +// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. +hisamitsu + +// hitachi : 2014-10-31 Hitachi, Ltd. +hitachi + +// hiv : 2014-03-13 +hiv + +// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited +hkt + +// hockey : 2015-03-19 Half Willow, LLC +hockey + +// holdings : 2013-08-27 John Madison, LLC +holdings + +// holiday : 2013-11-07 Goose Woods, LLC +holiday + +// homedepot : 2015-04-02 Homer TLC, Inc. +homedepot + +// homegoods : 2015-07-16 The TJX Companies, Inc. +homegoods + +// homes : 2014-01-09 DERHomes, LLC +homes + +// homesense : 2015-07-16 The TJX Companies, Inc. +homesense + +// honda : 2014-12-18 Honda Motor Co., Ltd. +honda + +// honeywell : 2015-07-23 Honeywell GTLD LLC +honeywell + +// horse : 2013-11-21 Top Level Domain Holdings Limited +horse + +// host : 2014-04-17 DotHost Inc. +host + +// hosting : 2014-05-29 Uniregistry, Corp. +hosting + +// hot : 2015-08-27 Amazon EU S.à r.l. +hot + +// hoteles : 2015-03-05 Travel Reservations SRL +hoteles + +// hotels : 2016-04-07 Booking.com B.V. +hotels + +// hotmail : 2014-12-18 Microsoft Corporation +hotmail + +// house : 2013-11-07 Sugar Park, LLC +house + +// how : 2014-01-23 Charleston Road Registry Inc. +how + +// hsbc : 2014-10-24 HSBC Holdings PLC +hsbc + +// htc : 2015-04-02 HTC corporation +htc + +// hughes : 2015-07-30 Hughes Satellite Systems Corporation +hughes + +// hyatt : 2015-07-30 Hyatt GTLD, L.L.C. +hyatt + +// hyundai : 2015-07-09 Hyundai Motor Company +hyundai + +// ibm : 2014-07-31 International Business Machines Corporation +ibm + +// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited +icbc + +// ice : 2014-10-30 IntercontinentalExchange, Inc. +ice + +// icu : 2015-01-08 One.com A/S +icu + +// ieee : 2015-07-23 IEEE Global LLC +ieee + +// ifm : 2014-01-30 ifm electronic gmbh +ifm + +// iinet : 2014-07-03 Connect West Pty. Ltd. +iinet + +// ikano : 2015-07-09 Ikano S.A. +ikano + +// imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) +imamat + +// imdb : 2015-06-25 Amazon EU S.à r.l. +imdb + +// immo : 2014-07-10 Auburn Bloom, LLC +immo + +// immobilien : 2013-11-07 United TLD Holdco Ltd. +immobilien + +// industries : 2013-12-05 Outer House, LLC +industries + +// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. +infiniti + +// ing : 2014-01-23 Charleston Road Registry Inc. +ing + +// ink : 2013-12-05 Top Level Design, LLC +ink + +// institute : 2013-11-07 Outer Maple, LLC +institute + +// insurance : 2015-02-19 fTLD Registry Services LLC +insurance + +// insure : 2014-03-20 Pioneer Willow, LLC +insure + +// intel : 2015-08-06 Intel Corporation +intel + +// international : 2013-11-07 Wild Way, LLC +international + +// intuit : 2015-07-30 Intuit Administrative Services, Inc. +intuit + +// investments : 2014-03-20 Holly Glen, LLC +investments + +// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A. +ipiranga + +// irish : 2014-08-07 Dot-Irish LLC +irish + +// iselect : 2015-02-11 iSelect Ltd +iselect + +// ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) +ismaili + +// ist : 2014-08-28 Istanbul Metropolitan Municipality +ist + +// istanbul : 2014-08-28 Istanbul Metropolitan Municipality +istanbul + +// itau : 2014-10-02 Itau Unibanco Holding S.A. +itau + +// itv : 2015-07-09 ITV Services Limited +itv + +// iveco : 2015-09-03 CNH Industrial N.V. +iveco + +// iwc : 2014-06-23 Richemont DNS Inc. +iwc + +// jaguar : 2014-11-13 Jaguar Land Rover Ltd +jaguar + +// java : 2014-06-19 Oracle Corporation +java + +// jcb : 2014-11-20 JCB Co., Ltd. +jcb + +// jcp : 2015-04-23 JCP Media, Inc. +jcp + +// jeep : 2015-07-30 FCA US LLC. +jeep + +// jetzt : 2014-01-09 +jetzt + +// jewelry : 2015-03-05 Wild Bloom, LLC +jewelry + +// jio : 2015-04-02 Affinity Names, Inc. +jio + +// jlc : 2014-12-04 Richemont DNS Inc. +jlc + +// jll : 2015-04-02 Jones Lang LaSalle Incorporated +jll + +// jmp : 2015-03-26 Matrix IP LLC +jmp + +// jnj : 2015-06-18 Johnson & Johnson Services, Inc. +jnj + +// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry +joburg + +// jot : 2014-12-18 Amazon EU S.à r.l. +jot + +// joy : 2014-12-18 Amazon EU S.à r.l. +joy + +// jpmorgan : 2015-04-30 JPMorgan Chase & Co. +jpmorgan + +// jprs : 2014-09-18 Japan Registry Services Co., Ltd. +jprs + +// juegos : 2014-03-20 Uniregistry, Corp. +juegos + +// juniper : 2015-07-30 JUNIPER NETWORKS, INC. +juniper + +// kaufen : 2013-11-07 United TLD Holdco Ltd. +kaufen + +// kddi : 2014-09-12 KDDI CORPORATION +kddi + +// kerryhotels : 2015-04-30 Kerry Trading Co. Limited +kerryhotels + +// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited +kerrylogistics + +// kerryproperties : 2015-04-09 Kerry Trading Co. Limited +kerryproperties + +// kfh : 2014-12-04 Kuwait Finance House +kfh + +// kia : 2015-07-09 KIA MOTORS CORPORATION +kia + +// kim : 2013-09-23 Afilias Limited +kim + +// kinder : 2014-11-07 Ferrero Trading Lux S.A. +kinder + +// kindle : 2015-06-25 Amazon EU S.à r.l. +kindle + +// kitchen : 2013-09-20 Just Goodbye, LLC +kitchen + +// kiwi : 2013-09-20 DOT KIWI LIMITED +kiwi + +// koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH +koeln + +// komatsu : 2015-01-08 Komatsu Ltd. +komatsu + +// kosher : 2015-08-20 Kosher Marketing Assets LLC +kosher + +// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft) +kpmg + +// kpn : 2015-01-08 Koninklijke KPN N.V. +kpn + +// krd : 2013-12-05 KRG Department of Information Technology +krd + +// kred : 2013-12-19 KredTLD Pty Ltd +kred + +// kuokgroup : 2015-04-09 Kerry Trading Co. Limited +kuokgroup + +// kyknet : 2015-03-05 Electronic Media Network (Pty) Ltd +kyknet + +// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen +kyoto + +// lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA +lacaixa + +// ladbrokes : 2015-08-06 LADBROKES INTERNATIONAL PLC +ladbrokes + +// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A. +lamborghini + +// lamer : 2015-10-01 The Estée Lauder Companies Inc. +lamer + +// lancaster : 2015-02-12 LANCASTER +lancaster + +// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V. +lancia + +// lancome : 2015-07-23 L'Oréal +lancome + +// land : 2013-09-10 Pine Moon, LLC +land + +// landrover : 2014-11-13 Jaguar Land Rover Ltd +landrover + +// lanxess : 2015-07-30 LANXESS Corporation +lanxess + +// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated +lasalle + +// lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico +lat + +// latino : 2015-07-30 Dish DBS Corporation +latino + +// latrobe : 2014-06-16 La Trobe University +latrobe + +// law : 2015-01-22 Minds + Machines Group Limited +law + +// lawyer : 2014-03-20 +lawyer + +// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") +lds + +// lease : 2014-03-06 Victor Trail, LLC +lease + +// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc +leclerc + +// lefrak : 2015-07-16 LeFrak Organization, Inc. +lefrak + +// legal : 2014-10-16 Blue Falls, LLC +legal + +// lego : 2015-07-16 LEGO Juris A/S +lego + +// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION +lexus + +// lgbt : 2014-05-08 Afilias Limited +lgbt + +// liaison : 2014-10-02 Liaison Technologies, Incorporated +liaison + +// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +lidl + +// life : 2014-02-06 Trixy Oaks, LLC +life + +// lifeinsurance : 2015-01-15 American Council of Life Insurers +lifeinsurance + +// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc. +lifestyle + +// lighting : 2013-08-27 John McCook, LLC +lighting + +// like : 2014-12-18 Amazon EU S.à r.l. +like + +// lilly : 2015-07-31 Eli Lilly and Company +lilly + +// limited : 2014-03-06 Big Fest, LLC +limited + +// limo : 2013-10-17 Hidden Frostbite, LLC +limo + +// lincoln : 2014-11-13 Ford Motor Company +lincoln + +// linde : 2014-12-04 Linde Aktiengesellschaft +linde + +// link : 2013-11-14 Uniregistry, Corp. +link + +// lipsy : 2015-06-25 Lipsy Ltd +lipsy + +// live : 2014-12-04 +live + +// living : 2015-07-30 Lifestyle Domain Holdings, Inc. +living + +// lixil : 2015-03-19 LIXIL Group Corporation +lixil + +// loan : 2014-11-20 dot Loan Limited +loan + +// loans : 2014-03-20 June Woods, LLC +loans + +// locker : 2015-06-04 Dish DBS Corporation +locker + +// locus : 2015-06-25 Locus Analytics LLC +locus + +// loft : 2015-07-30 Annco, Inc. +loft + +// lol : 2015-01-30 Uniregistry, Corp. +lol + +// london : 2013-11-14 Dot London Domains Limited +london + +// lotte : 2014-11-07 Lotte Holdings Co., Ltd. +lotte + +// lotto : 2014-04-10 Afilias Limited +lotto + +// love : 2014-12-22 Merchant Law Group LLP +love + +// lpl : 2015-07-30 LPL Holdings, Inc. +lpl + +// lplfinancial : 2015-07-30 LPL Holdings, Inc. +lplfinancial + +// ltd : 2014-09-25 Over Corner, LLC +ltd + +// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA +ltda + +// lundbeck : 2015-08-06 H. Lundbeck A/S +lundbeck + +// lupin : 2014-11-07 LUPIN LIMITED +lupin + +// luxe : 2014-01-09 Top Level Domain Holdings Limited +luxe + +// luxury : 2013-10-17 Luxury Partners, LLC +luxury + +// macys : 2015-07-31 Macys, Inc. +macys + +// madrid : 2014-05-01 Comunidad de Madrid +madrid + +// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF) +maif + +// maison : 2013-12-05 Victor Frostbite, LLC +maison + +// makeup : 2015-01-15 L'Oréal +makeup + +// man : 2014-12-04 MAN SE +man + +// management : 2013-11-07 John Goodbye, LLC +management + +// mango : 2013-10-24 PUNTO FA S.L. +mango + +// market : 2014-03-06 +market + +// marketing : 2013-11-07 Fern Pass, LLC +marketing + +// markets : 2014-12-11 IG Group Holdings PLC +markets + +// marriott : 2014-10-09 Marriott Worldwide Corporation +marriott + +// marshalls : 2015-07-16 The TJX Companies, Inc. +marshalls + +// maserati : 2015-07-31 Fiat Chrysler Automobiles N.V. +maserati + +// mattel : 2015-08-06 Mattel Sites, Inc. +mattel + +// mba : 2015-04-02 Lone Hollow, LLC +mba + +// mcd : 2015-07-30 McDonald’s Corporation +mcd + +// mcdonalds : 2015-07-30 McDonald’s Corporation +mcdonalds + +// mckinsey : 2015-07-31 McKinsey Holdings, Inc. +mckinsey + +// med : 2015-08-06 Medistry LLC +med + +// media : 2014-03-06 Grand Glen, LLC +media + +// meet : 2014-01-16 +meet + +// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation +melbourne + +// meme : 2014-01-30 Charleston Road Registry Inc. +meme + +// memorial : 2014-10-16 Dog Beach, LLC +memorial + +// men : 2015-02-26 Exclusive Registry Limited +men + +// menu : 2013-09-11 Wedding TLD2, LLC +menu + +// meo : 2014-11-07 PT Comunicacoes S.A. +meo + +// metlife : 2015-05-07 MetLife Services and Solutions, LLC +metlife + +// miami : 2013-12-19 Top Level Domain Holdings Limited +miami + +// microsoft : 2014-12-18 Microsoft Corporation +microsoft + +// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft +mini + +// mint : 2015-07-30 Intuit Administrative Services, Inc. +mint + +// mit : 2015-07-02 Massachusetts Institute of Technology +mit + +// mitsubishi : 2015-07-23 Mitsubishi Corporation +mitsubishi + +// mlb : 2015-05-21 MLB Advanced Media DH, LLC +mlb + +// mls : 2015-04-23 The Canadian Real Estate Association +mls + +// mma : 2014-11-07 MMA IARD +mma + +// mnet : 2015-03-05 Electronic Media Network (Pty) Ltd +mnet + +// mobily : 2014-12-18 GreenTech Consultancy Company W.L.L. +mobily + +// moda : 2013-11-07 United TLD Holdco Ltd. +moda + +// moe : 2013-11-13 Interlink Co., Ltd. +moe + +// moi : 2014-12-18 Amazon EU S.à r.l. +moi + +// mom : 2015-04-16 Uniregistry, Corp. +mom + +// monash : 2013-09-30 Monash University +monash + +// money : 2014-10-16 Outer McCook, LLC +money + +// monster : 2015-09-11 Monster Worldwide, Inc. +monster + +// montblanc : 2014-06-23 Richemont DNS Inc. +montblanc + +// mopar : 2015-07-30 FCA US LLC. +mopar + +// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") +mormon + +// mortgage : 2014-03-20 +mortgage + +// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +moscow + +// moto : 2015-06-04 Charleston Road Registry Inc. +moto + +// motorcycles : 2014-01-09 DERMotorcycles, LLC +motorcycles + +// mov : 2014-01-30 Charleston Road Registry Inc. +mov + +// movie : 2015-02-05 New Frostbite, LLC +movie + +// movistar : 2014-10-16 Telefónica S.A. +movistar + +// msd : 2015-07-23 MSD Registry Holdings, Inc. +msd + +// mtn : 2014-12-04 MTN Dubai Limited +mtn + +// mtpc : 2014-11-20 Mitsubishi Tanabe Pharma Corporation +mtpc + +// mtr : 2015-03-12 MTR Corporation Limited +mtr + +// multichoice : 2015-03-12 MultiChoice (Proprietary) Limited +multichoice + +// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC +mutual + +// mutuelle : 2015-06-18 Fédération Nationale de la Mutualité Française +mutuelle + +// mzansimagic : 2015-03-05 Electronic Media Network (Pty) Ltd +mzansimagic + +// nab : 2015-08-20 National Australia Bank Limited +nab + +// nadex : 2014-12-11 IG Group Holdings PLC +nadex + +// nagoya : 2013-10-24 GMO Registry, Inc. +nagoya + +// naspers : 2015-02-12 Intelprop (Proprietary) Limited +naspers + +// nationwide : 2015-07-23 Nationwide Mutual Insurance Company +nationwide + +// natura : 2015-03-12 NATURA COSMÉTICOS S.A. +natura + +// navy : 2014-03-06 United TLD Holdco Ltd. +navy + +// nba : 2015-07-31 NBA REGISTRY, LLC +nba + +// nec : 2015-01-08 NEC Corporation +nec + +// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA +netbank + +// netflix : 2015-06-18 Netflix, Inc. +netflix + +// network : 2013-11-14 Trixy Manor, LLC +network + +// neustar : 2013-12-05 NeuStar, Inc. +neustar + +// new : 2014-01-30 Charleston Road Registry Inc. +new + +// newholland : 2015-09-03 CNH Industrial N.V. +newholland + +// news : 2014-12-18 +news + +// next : 2015-06-18 Next plc +next + +// nextdirect : 2015-06-18 Next plc +nextdirect + +// nexus : 2014-07-24 Charleston Road Registry Inc. +nexus + +// nfl : 2015-07-23 NFL Reg Ops LLC +nfl + +// ngo : 2014-03-06 Public Interest Registry +ngo + +// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK) +nhk + +// nico : 2014-12-04 DWANGO Co., Ltd. +nico + +// nike : 2015-07-23 NIKE, Inc. +nike + +// nikon : 2015-05-21 NIKON CORPORATION +nikon + +// ninja : 2013-11-07 United TLD Holdco Ltd. +ninja + +// nissan : 2014-03-27 NISSAN MOTOR CO., LTD. +nissan + +// nissay : 2015-10-29 Nippon Life Insurance Company +nissay + +// nokia : 2015-01-08 Nokia Corporation +nokia + +// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC +northwesternmutual + +// norton : 2014-12-04 Symantec Corporation +norton + +// now : 2015-06-25 Amazon EU S.à r.l. +now + +// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +nowruz + +// nowtv : 2015-05-14 Starbucks (HK) Limited +nowtv + +// nra : 2014-05-22 NRA Holdings Company, INC. +nra + +// nrw : 2013-11-21 Minds + Machines GmbH +nrw + +// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION +ntt + +// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications +nyc + +// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA +obi + +// observer : 2015-04-30 Guardian News and Media Limited +observer + +// off : 2015-07-23 Johnson Shareholdings, Inc. +off + +// office : 2015-03-12 Microsoft Corporation +office + +// okinawa : 2013-12-05 BusinessRalliart Inc. +okinawa + +// olayan : 2015-05-14 Crescent Holding GmbH +olayan + +// olayangroup : 2015-05-14 Crescent Holding GmbH +olayangroup + +// oldnavy : 2015-07-31 The Gap, Inc. +oldnavy + +// ollo : 2015-06-04 Dish DBS Corporation +ollo + +// omega : 2015-01-08 The Swatch Group Ltd +omega + +// one : 2014-11-07 One.com A/S +one + +// ong : 2014-03-06 Public Interest Registry +ong + +// onl : 2013-09-16 I-Registry Ltd. +onl + +// online : 2015-01-15 DotOnline Inc. +online + +// onyourside : 2015-07-23 Nationwide Mutual Insurance Company +onyourside + +// ooo : 2014-01-09 INFIBEAM INCORPORATION LIMITED +ooo + +// open : 2015-07-31 American Express Travel Related Services Company, Inc. +open + +// oracle : 2014-06-19 Oracle Corporation +oracle + +// orange : 2015-03-12 Orange Brand Services Limited +orange + +// organic : 2014-03-27 Afilias Limited +organic + +// orientexpress : 2015-02-05 Belmond Ltd. +orientexpress + +// origins : 2015-10-01 The Estée Lauder Companies Inc. +origins + +// osaka : 2014-09-04 Interlink Co., Ltd. +osaka + +// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd. +otsuka + +// ott : 2015-06-04 Dish DBS Corporation +ott + +// ovh : 2014-01-16 OVH SAS +ovh + +// page : 2014-12-04 Charleston Road Registry Inc. +page + +// pamperedchef : 2015-02-05 The Pampered Chef, Ltd. +pamperedchef + +// panasonic : 2015-07-30 Panasonic Corporation +panasonic + +// panerai : 2014-11-07 Richemont DNS Inc. +panerai + +// paris : 2014-01-30 City of Paris +paris + +// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +pars + +// partners : 2013-12-05 Magic Glen, LLC +partners + +// parts : 2013-12-05 Sea Goodbye, LLC +parts + +// party : 2014-09-11 Blue Sky Registry Limited +party + +// passagens : 2015-03-05 Travel Reservations SRL +passagens + +// pay : 2015-08-27 Amazon EU S.à r.l. +pay + +// payu : 2015-02-12 MIH PayU B.V. +payu + +// pccw : 2015-05-14 PCCW Enterprises Limited +pccw + +// pet : 2015-05-07 Afilias plc +pet + +// pfizer : 2015-09-11 Pfizer Inc. +pfizer + +// pharmacy : 2014-06-19 National Association of Boards of Pharmacy +pharmacy + +// philips : 2014-11-07 Koninklijke Philips N.V. +philips + +// photo : 2013-11-14 Uniregistry, Corp. +photo + +// photography : 2013-09-20 Sugar Glen, LLC +photography + +// photos : 2013-10-17 Sea Corner, LLC +photos + +// physio : 2014-05-01 PhysBiz Pty Ltd +physio + +// piaget : 2014-10-16 Richemont DNS Inc. +piaget + +// pics : 2013-11-14 Uniregistry, Corp. +pics + +// pictet : 2014-06-26 Pictet Europe S.A. +pictet + +// pictures : 2014-03-06 Foggy Sky, LLC +pictures + +// pid : 2015-01-08 Top Level Spectrum, Inc. +pid + +// pin : 2014-12-18 Amazon EU S.à r.l. +pin + +// ping : 2015-06-11 Ping Registry Provider, Inc. +ping + +// pink : 2013-10-01 Afilias Limited +pink + +// pioneer : 2015-07-16 Pioneer Corporation +pioneer + +// pizza : 2014-06-26 Foggy Moon, LLC +pizza + +// place : 2014-04-24 Snow Galley, LLC +place + +// play : 2015-03-05 Charleston Road Registry Inc. +play + +// playstation : 2015-07-02 Sony Computer Entertainment Inc. +playstation + +// plumbing : 2013-09-10 Spring Tigers, LLC +plumbing + +// plus : 2015-02-05 Sugar Mill, LLC +plus + +// pnc : 2015-07-02 PNC Domain Co., LLC +pnc + +// pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +pohl + +// poker : 2014-07-03 Afilias Domains No. 5 Limited +poker + +// politie : 2015-08-20 Politie Nederland +politie + +// porn : 2014-10-16 ICM Registry PN LLC +porn + +// pramerica : 2015-07-30 Prudential Financial, Inc. +pramerica + +// praxi : 2013-12-05 Praxi S.p.A. +praxi + +// press : 2014-04-03 DotPress Inc. +press + +// prime : 2015-06-25 Amazon EU S.à r.l. +prime + +// prod : 2014-01-23 Charleston Road Registry Inc. +prod + +// productions : 2013-12-05 Magic Birch, LLC +productions + +// prof : 2014-07-24 Charleston Road Registry Inc. +prof + +// progressive : 2015-07-23 Progressive Casualty Insurance Company +progressive + +// promo : 2014-12-18 +promo + +// properties : 2013-12-05 Big Pass, LLC +properties + +// property : 2014-05-22 Uniregistry, Corp. +property + +// protection : 2015-04-23 +protection + +// pru : 2015-07-30 Prudential Financial, Inc. +pru + +// prudential : 2015-07-30 Prudential Financial, Inc. +prudential + +// pub : 2013-12-12 United TLD Holdco Ltd. +pub + +// pwc : 2015-10-29 PricewaterhouseCoopers LLP +pwc + +// qpon : 2013-11-14 dotCOOL, Inc. +qpon + +// quebec : 2013-12-19 PointQuébec Inc +quebec + +// quest : 2015-03-26 Quest ION Limited +quest + +// qvc : 2015-07-30 QVC, Inc. +qvc + +// racing : 2014-12-04 Premier Registry Limited +racing + +// raid : 2015-07-23 Johnson Shareholdings, Inc. +raid + +// read : 2014-12-18 Amazon EU S.à r.l. +read + +// realestate : 2015-09-11 dotRealEstate LLC +realestate + +// realtor : 2014-05-29 Real Estate Domains LLC +realtor + +// realty : 2015-03-19 Fegistry, LLC +realty + +// recipes : 2013-10-17 Grand Island, LLC +recipes + +// red : 2013-11-07 Afilias Limited +red + +// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd. +redstone + +// redumbrella : 2015-03-26 Travelers TLD, LLC +redumbrella + +// rehab : 2014-03-06 United TLD Holdco Ltd. +rehab + +// reise : 2014-03-13 +reise + +// reisen : 2014-03-06 New Cypress, LLC +reisen + +// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc. +reit + +// reliance : 2015-04-02 Reliance Industries Limited +reliance + +// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd. +ren + +// rent : 2014-12-04 DERRent, LLC +rent + +// rentals : 2013-12-05 Big Hollow,LLC +rentals + +// repair : 2013-11-07 Lone Sunset, LLC +repair + +// report : 2013-12-05 Binky Glen, LLC +report + +// republican : 2014-03-20 United TLD Holdco Ltd. +republican + +// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +rest + +// restaurant : 2014-07-03 Snow Avenue, LLC +restaurant + +// review : 2014-11-20 dot Review Limited +review + +// reviews : 2013-09-13 +reviews + +// rexroth : 2015-06-18 Robert Bosch GMBH +rexroth + +// rich : 2013-11-21 I-Registry Ltd. +rich + +// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited +richardli + +// ricoh : 2014-11-20 Ricoh Company, Ltd. +ricoh + +// rightathome : 2015-07-23 Johnson Shareholdings, Inc. +rightathome + +// ril : 2015-04-02 Reliance Industries Limited +ril + +// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO +rio + +// rip : 2014-07-10 United TLD Holdco Ltd. +rip + +// rmit : 2015-11-19 Royal Melbourne Institute of Technology +rmit + +// rocher : 2014-12-18 Ferrero Trading Lux S.A. +rocher + +// rocks : 2013-11-14 +rocks + +// rodeo : 2013-12-19 Top Level Domain Holdings Limited +rodeo + +// rogers : 2015-08-06 Rogers Communications Partnership +rogers + +// room : 2014-12-18 Amazon EU S.à r.l. +room + +// rsvp : 2014-05-08 Charleston Road Registry Inc. +rsvp + +// ruhr : 2013-10-02 regiodot GmbH & Co. KG +ruhr + +// run : 2015-03-19 Snow Park, LLC +run + +// rwe : 2015-04-02 RWE AG +rwe + +// ryukyu : 2014-01-09 BusinessRalliart Inc. +ryukyu + +// saarland : 2013-12-12 dotSaarland GmbH +saarland + +// safe : 2014-12-18 Amazon EU S.à r.l. +safe + +// safety : 2015-01-08 Safety Registry Services, LLC. +safety + +// sakura : 2014-12-18 SAKURA Internet Inc. +sakura + +// sale : 2014-10-16 +sale + +// salon : 2014-12-11 Outer Orchard, LLC +salon + +// samsclub : 2015-07-31 Wal-Mart Stores, Inc. +samsclub + +// samsung : 2014-04-03 SAMSUNG SDS CO., LTD +samsung + +// sandvik : 2014-11-13 Sandvik AB +sandvik + +// sandvikcoromant : 2014-11-07 Sandvik AB +sandvikcoromant + +// sanofi : 2014-10-09 Sanofi +sanofi + +// sap : 2014-03-27 SAP AG +sap + +// sapo : 2014-11-07 PT Comunicacoes S.A. +sapo + +// sarl : 2014-07-03 Delta Orchard, LLC +sarl + +// sas : 2015-04-02 Research IP LLC +sas + +// save : 2015-06-25 Amazon EU S.à r.l. +save + +// saxo : 2014-10-31 Saxo Bank A/S +saxo + +// sbi : 2015-03-12 STATE BANK OF INDIA +sbi + +// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION +sbs + +// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) +sca + +// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB") +scb + +// schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG +schaeffler + +// schmidt : 2014-04-03 SALM S.A.S. +schmidt + +// scholarships : 2014-04-24 Scholarships.com, LLC +scholarships + +// school : 2014-12-18 Little Galley, LLC +school + +// schule : 2014-03-06 Outer Moon, LLC +schule + +// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG +schwarz + +// science : 2014-09-11 dot Science Limited +science + +// scjohnson : 2015-07-23 Johnson Shareholdings, Inc. +scjohnson + +// scor : 2014-10-31 SCOR SE +scor + +// scot : 2014-01-23 Dot Scot Registry Limited +scot + +// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) +seat + +// secure : 2015-08-27 Amazon EU S.à r.l. +secure + +// security : 2015-05-14 +security + +// seek : 2014-12-04 Seek Limited +seek + +// select : 2015-10-08 iSelect Ltd +select + +// sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A. +sener + +// services : 2014-02-27 Fox Castle, LLC +services + +// ses : 2015-07-23 SES +ses + +// seven : 2015-08-06 Seven West Media Ltd +seven + +// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG +sew + +// sex : 2014-11-13 ICM Registry SX LLC +sex + +// sexy : 2013-09-11 Uniregistry, Corp. +sexy + +// sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR +sfr + +// shangrila : 2015-09-03 Shangri‐La International Hotel Management Limited +shangrila + +// sharp : 2014-05-01 Sharp Corporation +sharp + +// shaw : 2015-04-23 Shaw Cablesystems G.P. +shaw + +// shell : 2015-07-30 Shell Information Technology International Inc +shell + +// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +shia + +// shiksha : 2013-11-14 Afilias Limited +shiksha + +// shoes : 2013-10-02 Binky Galley, LLC +shoes + +// shop : 2016-04-08 GMO Registry, Inc. +shop + +// shopping : 2016-03-31 +shopping + +// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +shouji + +// show : 2015-03-05 Snow Beach, LLC +show + +// showtime : 2015-08-06 CBS Domains Inc. +showtime + +// shriram : 2014-01-23 Shriram Capital Ltd. +shriram + +// silk : 2015-06-25 Amazon EU S.à r.l. +silk + +// sina : 2015-03-12 Sina Corporation +sina + +// singles : 2013-08-27 Fern Madison, LLC +singles + +// site : 2015-01-15 DotSite Inc. +site + +// ski : 2015-04-09 STARTING DOT LIMITED +ski + +// skin : 2015-01-15 L'Oréal +skin + +// sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch +sky + +// skype : 2014-12-18 Microsoft Corporation +skype + +// sling : 2015-07-30 Hughes Satellite Systems Corporation +sling + +// smart : 2015-07-09 Smart Communications, Inc. (SMART) +smart + +// smile : 2014-12-18 Amazon EU S.à r.l. +smile + +// sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F +sncf + +// soccer : 2015-03-26 Foggy Shadow, LLC +soccer + +// social : 2013-11-07 United TLD Holdco Ltd. +social + +// softbank : 2015-07-02 SoftBank Corp. +softbank + +// software : 2014-03-20 +software + +// sohu : 2013-12-19 Sohu.com Limited +sohu + +// solar : 2013-11-07 Ruby Town, LLC +solar + +// solutions : 2013-11-07 Silver Cover, LLC +solutions + +// song : 2015-02-26 Amazon EU S.à r.l. +song + +// sony : 2015-01-08 Sony Corporation +sony + +// soy : 2014-01-23 Charleston Road Registry Inc. +soy + +// space : 2014-04-03 DotSpace Inc. +space + +// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG +spiegel + +// spot : 2015-02-26 Amazon EU S.à r.l. +spot + +// spreadbetting : 2014-12-11 IG Group Holdings PLC +spreadbetting + +// srl : 2015-05-07 mySRL GmbH +srl + +// srt : 2015-07-30 FCA US LLC. +srt + +// stada : 2014-11-13 STADA Arzneimittel AG +stada + +// staples : 2015-07-30 Staples, Inc. +staples + +// star : 2015-01-08 Star India Private Limited +star + +// starhub : 2015-02-05 StarHub Ltd +starhub + +// statebank : 2015-03-12 STATE BANK OF INDIA +statebank + +// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company +statefarm + +// statoil : 2014-12-04 Statoil ASA +statoil + +// stc : 2014-10-09 Saudi Telecom Company +stc + +// stcgroup : 2014-10-09 Saudi Telecom Company +stcgroup + +// stockholm : 2014-12-18 Stockholms kommun +stockholm + +// storage : 2014-12-22 Self Storage Company LLC +storage + +// store : 2015-04-09 DotStore Inc. +store + +// stream : 2016-01-08 dot Stream Limited +stream + +// studio : 2015-02-11 +studio + +// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD +study + +// style : 2014-12-04 Binky Moon, LLC +style + +// sucks : 2014-12-22 Vox Populi Registry Inc. +sucks + +// supersport : 2015-03-05 SuperSport International Holdings Proprietary Limited +supersport + +// supplies : 2013-12-19 Atomic Fields, LLC +supplies + +// supply : 2013-12-19 Half Falls, LLC +supply + +// support : 2013-10-24 Grand Orchard, LLC +support + +// surf : 2014-01-09 Top Level Domain Holdings Limited +surf + +// surgery : 2014-03-20 Tin Avenue, LLC +surgery + +// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION +suzuki + +// swatch : 2015-01-08 The Swatch Group Ltd +swatch + +// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited +swiftcover + +// swiss : 2014-10-16 Swiss Confederation +swiss + +// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet +sydney + +// symantec : 2014-12-04 Symantec Corporation +symantec + +// systems : 2013-11-07 Dash Cypress, LLC +systems + +// tab : 2014-12-04 Tabcorp Holdings Limited +tab + +// taipei : 2014-07-10 Taipei City Government +taipei + +// talk : 2015-04-09 Amazon EU S.à r.l. +talk + +// taobao : 2015-01-15 Alibaba Group Holding Limited +taobao + +// target : 2015-07-31 Target Domain Holdings, LLC +target + +// tatamotors : 2015-03-12 Tata Motors Ltd +tatamotors + +// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" +tatar + +// tattoo : 2013-08-30 Uniregistry, Corp. +tattoo + +// tax : 2014-03-20 Storm Orchard, LLC +tax + +// taxi : 2015-03-19 Pine Falls, LLC +taxi + +// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +tci + +// tdk : 2015-06-11 TDK Corporation +tdk + +// team : 2015-03-05 Atomic Lake, LLC +team + +// tech : 2015-01-30 Dot Tech LLC +tech + +// technology : 2013-09-13 Auburn Falls +technology + +// telecity : 2015-02-19 TelecityGroup International Limited +telecity + +// telefonica : 2014-10-16 Telefónica S.A. +telefonica + +// temasek : 2014-08-07 Temasek Holdings (Private) Limited +temasek + +// tennis : 2014-12-04 Cotton Bloom, LLC +tennis + +// teva : 2015-07-02 Teva Pharmaceutical Industries Limited +teva + +// thd : 2015-04-02 Homer TLC, Inc. +thd + +// theater : 2015-03-19 Blue Tigers, LLC +theater + +// theatre : 2015-05-07 +theatre + +// theguardian : 2015-04-30 Guardian News and Media Limited +theguardian + +// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America +tiaa + +// tickets : 2015-02-05 Accent Media Limited +tickets + +// tienda : 2013-11-14 Victor Manor, LLC +tienda + +// tiffany : 2015-01-30 Tiffany and Company +tiffany + +// tips : 2013-09-20 Corn Willow, LLC +tips + +// tires : 2014-11-07 Dog Edge, LLC +tires + +// tirol : 2014-04-24 punkt Tirol GmbH +tirol + +// tjmaxx : 2015-07-16 The TJX Companies, Inc. +tjmaxx + +// tjx : 2015-07-16 The TJX Companies, Inc. +tjx + +// tkmaxx : 2015-07-16 The TJX Companies, Inc. +tkmaxx + +// tmall : 2015-01-15 Alibaba Group Holding Limited +tmall + +// today : 2013-09-20 Pearl Woods, LLC +today + +// tokyo : 2013-11-13 GMO Registry, Inc. +tokyo + +// tools : 2013-11-21 Pioneer North, LLC +tools + +// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd. +top + +// toray : 2014-12-18 Toray Industries, Inc. +toray + +// toshiba : 2014-04-10 TOSHIBA Corporation +toshiba + +// total : 2015-08-06 Total SA +total + +// tours : 2015-01-22 Sugar Station, LLC +tours + +// town : 2014-03-06 Koko Moon, LLC +town + +// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION +toyota + +// toys : 2014-03-06 Pioneer Orchard, LLC +toys + +// trade : 2014-01-23 Elite Registry Limited +trade + +// trading : 2014-12-11 IG Group Holdings PLC +trading + +// training : 2013-11-07 Wild Willow, LLC +training + +// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. +travelchannel + +// travelers : 2015-03-26 Travelers TLD, LLC +travelers + +// travelersinsurance : 2015-03-26 Travelers TLD, LLC +travelersinsurance + +// trust : 2014-10-16 +trust + +// trv : 2015-03-26 Travelers TLD, LLC +trv + +// tube : 2015-06-11 Latin American Telecom LLC +tube + +// tui : 2014-07-03 TUI AG +tui + +// tunes : 2015-02-26 Amazon EU S.à r.l. +tunes + +// tushu : 2014-12-18 Amazon EU S.à r.l. +tushu + +// tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED +tvs + +// ubank : 2015-08-20 National Australia Bank Limited +ubank + +// ubs : 2014-12-11 UBS AG +ubs + +// uconnect : 2015-07-30 FCA US LLC. +uconnect + +// unicom : 2015-10-15 China United Network Communications Corporation Limited +unicom + +// university : 2014-03-06 Little Station, LLC +university + +// uno : 2013-09-11 Dot Latin LLC +uno + +// uol : 2014-05-01 UBN INTERNET LTDA. +uol + +// ups : 2015-06-25 UPS Market Driver, Inc. +ups + +// vacations : 2013-12-05 Atomic Tigers, LLC +vacations + +// vana : 2014-12-11 Lifestyle Domain Holdings, Inc. +vana + +// vanguard : 2015-09-03 The Vanguard Group, Inc. +vanguard + +// vegas : 2014-01-16 Dot Vegas, Inc. +vegas + +// ventures : 2013-08-27 Binky Lake, LLC +ventures + +// verisign : 2015-08-13 VeriSign, Inc. +verisign + +// versicherung : 2014-03-20 dotversicherung-registry GmbH +versicherung + +// vet : 2014-03-06 +vet + +// viajes : 2013-10-17 Black Madison, LLC +viajes + +// video : 2014-10-16 +video + +// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe +vig + +// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd. +viking + +// villas : 2013-12-05 New Sky, LLC +villas + +// vin : 2015-06-18 Holly Shadow, LLC +vin + +// vip : 2015-01-22 Minds + Machines Group Limited +vip + +// virgin : 2014-09-25 Virgin Enterprises Limited +virgin + +// visa : 2015-07-30 Visa Worldwide Pte. Limited +visa + +// vision : 2013-12-05 Koko Station, LLC +vision + +// vista : 2014-09-18 Vistaprint Limited +vista + +// vistaprint : 2014-09-18 Vistaprint Limited +vistaprint + +// viva : 2014-11-07 Saudi Telecom Company +viva + +// vivo : 2015-07-31 Telefonica Brasil S.A. +vivo + +// vlaanderen : 2014-02-06 DNS.be vzw +vlaanderen + +// vodka : 2013-12-19 Top Level Domain Holdings Limited +vodka + +// volkswagen : 2015-05-14 Volkswagen Group of America Inc. +volkswagen + +// volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag +volvo + +// vote : 2013-11-21 Monolith Registry LLC +vote + +// voting : 2013-11-13 Valuetainment Corp. +voting + +// voto : 2013-11-21 Monolith Registry LLC +voto + +// voyage : 2013-08-27 Ruby House, LLC +voyage + +// vuelos : 2015-03-05 Travel Reservations SRL +vuelos + +// wales : 2014-05-08 Nominet UK +wales + +// walmart : 2015-07-31 Wal-Mart Stores, Inc. +walmart + +// walter : 2014-11-13 Sandvik AB +walter + +// wang : 2013-10-24 Zodiac Leo Limited +wang + +// wanggou : 2014-12-18 Amazon EU S.à r.l. +wanggou + +// warman : 2015-06-18 Weir Group IP Limited +warman + +// watch : 2013-11-14 Sand Shadow, LLC +watch + +// watches : 2014-12-22 Richemont DNS Inc. +watches + +// weather : 2015-01-08 The Weather Channel, LLC +weather + +// weatherchannel : 2015-03-12 The Weather Channel, LLC +weatherchannel + +// webcam : 2014-01-23 dot Webcam Limited +webcam + +// weber : 2015-06-04 Saint-Gobain Weber SA +weber + +// website : 2014-04-03 DotWebsite Inc. +website + +// wed : 2013-10-01 Atgron, Inc. +wed + +// wedding : 2014-04-24 Top Level Domain Holdings Limited +wedding + +// weibo : 2015-03-05 Sina Corporation +weibo + +// weir : 2015-01-29 Weir Group IP Limited +weir + +// whoswho : 2014-02-20 Who's Who Registry +whoswho + +// wien : 2013-10-28 punkt.wien GmbH +wien + +// wiki : 2013-11-07 Top Level Design, LLC +wiki + +// williamhill : 2014-03-13 William Hill Organization Limited +williamhill + +// win : 2014-11-20 First Registry Limited +win + +// windows : 2014-12-18 Microsoft Corporation +windows + +// wine : 2015-06-18 June Station, LLC +wine + +// winners : 2015-07-16 The TJX Companies, Inc. +winners + +// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC +wme + +// wolterskluwer : 2015-08-06 Wolters Kluwer N.V. +wolterskluwer + +// woodside : 2015-07-09 Woodside Petroleum Limited +woodside + +// work : 2013-12-19 Top Level Domain Holdings Limited +work + +// works : 2013-11-14 Little Dynamite, LLC +works + +// world : 2014-06-12 Bitter Fields, LLC +world + +// wow : 2015-10-08 Amazon EU S.à r.l. +wow + +// wtc : 2013-12-19 World Trade Centers Association, Inc. +wtc + +// wtf : 2014-03-06 Hidden Way, LLC +wtf + +// xbox : 2014-12-18 Microsoft Corporation +xbox + +// xerox : 2014-10-24 Xerox DNHC LLC +xerox + +// xfinity : 2015-07-09 Comcast IP Holdings I, LLC +xfinity + +// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +xihuan + +// xin : 2014-12-11 Elegant Leader Limited +xin + +// xn--11b4c3d : 2015-01-15 VeriSign Sarl +कॉम + +// xn--1ck2e1b : 2015-02-26 Amazon EU S.à r.l. +セール + +// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd. +佛山 + +// xn--30rr7y : 2014-06-12 Excellent First Limited +慈善 + +// xn--3bst00m : 2013-09-13 Eagle Horizon Limited +集团 + +// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED +在线 + +// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. +大众汽车 + +// xn--3pxu8k : 2015-01-15 VeriSign Sarl +点看 + +// xn--42c2d9a : 2015-01-15 VeriSign Sarl +คอม + +// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited +八卦 + +// xn--4gbrim : 2013-10-04 Suhub Electronic Establishment +موقع + +// xn--4gq48lf9j : 2015-07-31 Wal-Mart Stores, Inc. +一号店 + +// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center +公益 + +// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +公司 + +// xn--5su34j936bgsg : 2015-09-03 Shangri‐La International Hotel Management Limited +香格里拉 + +// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited +网站 + +// xn--6frz82g : 2013-09-23 Afilias Limited +移动 + +// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited +我爱你 + +// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +москва + +// xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +католик + +// xn--80asehdb : 2013-07-14 CORE Association +онлайн + +// xn--80aswg : 2013-07-14 CORE Association +сайт + +// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited +联通 + +// xn--9dbq2a : 2015-01-15 VeriSign Sarl +קום + +// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED +时尚 + +// xn--9krt00a : 2015-03-12 Sina Corporation +微博 + +// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited +淡马锡 + +// xn--bck1b9a5dre4c : 2015-02-26 Amazon EU S.à r.l. +ファッション + +// xn--c1avg : 2013-11-14 Public Interest Registry +орг + +// xn--c2br7g : 2015-01-15 VeriSign Sarl +नेट + +// xn--cck2b3b : 2015-02-26 Amazon EU S.à r.l. +ストア + +// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD +삼성 + +// xn--czr694b : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED +商标 + +// xn--czrs0t : 2013-12-19 Wild Island, LLC +商店 + +// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited +商城 + +// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet” +дети + +// xn--eckvdtc9d : 2014-12-18 Amazon EU S.à r.l. +ポイント + +// xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 +新闻 + +// xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited +工行 + +// xn--fct429k : 2015-04-09 Amazon EU S.à r.l. +家電 + +// xn--fhbei : 2015-01-15 VeriSign Sarl +كوم + +// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED +中文网 + +// xn--fiq64b : 2013-10-14 CITIC Group Corporation +中信 + +// xn--fjq720a : 2014-05-22 Will Bloom, LLC +娱乐 + +// xn--flw351e : 2014-07-31 Charleston Road Registry Inc. +谷歌 + +// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited +電訊盈科 + +// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited +购物 + +// xn--gckr3f0f : 2015-02-26 Amazon EU S.à r.l. +クラウド + +// xn--gk3at1e : 2015-10-08 Amazon EU S.à r.l. +通販 + +// xn--hxt814e : 2014-05-15 Zodiac Libra Limited +网店 + +// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry +संगठन + +// xn--imr513n : 2014-12-11 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED +餐厅 + +// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) +网络 + +// xn--j1aef : 2015-01-15 VeriSign Sarl +ком + +// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation +诺基亚 + +// xn--jvr189m : 2015-02-26 Amazon EU S.à r.l. +食品 + +// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. +飞利浦 + +// xn--kpu716f : 2014-12-22 Richemont DNS Inc. +手表 + +// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd +手机 + +// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company +ارامكو + +// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH +العليان + +// xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) +اتصالات + +// xn--mgbab2bd : 2013-10-31 CORE Association +بازار + +// xn--mgbb9fbpob : 2014-12-18 GreenTech Consultancy Company W.L.L. +موبايلي + +// xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre +ابوظبي + +// xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +كاثوليك + +// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +همراه + +// xn--mk1bu44c : 2015-01-15 VeriSign Sarl +닷컴 + +// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd. +政府 + +// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd. +شبكة + +// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House +بيتك + +// xn--ngbrx : 2015-11-12 League of Arab States +عرب + +// xn--nqv7f : 2013-11-14 Public Interest Registry +机构 + +// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry +组织机构 + +// xn--nyqy26a : 2014-11-07 Stable Tone Limited +健康 + +// xn--p1acf : 2013-12-12 Rusnames Limited +рус + +// xn--pbt977c : 2014-12-22 Richemont DNS Inc. +珠宝 + +// xn--pssy2u : 2015-01-15 VeriSign Sarl +大拿 + +// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc. +みんな + +// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc. +グーグル + +// xn--rhqv96g : 2013-09-11 Stable Tone Limited +世界 + +// xn--rovu88b : 2015-02-26 Amazon EU S.à r.l. +書籍 + +// xn--ses554g : 2014-01-16 +网址 + +// xn--t60b56a : 2015-01-15 VeriSign Sarl +닷넷 + +// xn--tckwe : 2015-01-15 VeriSign Sarl +コム + +// xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +天主教 + +// xn--unup4y : 2013-07-14 Spring Fields, LLC +游戏 + +// xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberater + +// xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG +vermögensberatung + +// xn--vhquv : 2013-08-27 Dash McCook, LLC +企业 + +// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd. +信息 + +// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited +嘉里大酒店 + +// xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited +嘉里 + +// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd. +广东 + +// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center +政务 + +// xperia : 2015-05-14 Sony Mobile Communications AB +xperia + +// xyz : 2013-12-05 XYZ.COM LLC +xyz + +// yachts : 2014-01-09 DERYachts, LLC +yachts + +// yahoo : 2015-04-02 Yahoo! Domain Services Inc. +yahoo + +// yamaxun : 2014-12-18 Amazon EU S.à r.l. +yamaxun + +// yandex : 2014-04-10 YANDEX, LLC +yandex + +// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. +yodobashi + +// yoga : 2014-05-29 Top Level Domain Holdings Limited +yoga + +// yokohama : 2013-12-12 GMO Registry, Inc. +yokohama + +// you : 2015-04-09 Amazon EU S.à r.l. +you + +// youtube : 2014-05-01 Charleston Road Registry Inc. +youtube + +// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +yun + +// zappos : 2015-06-25 Amazon EU S.à r.l. +zappos + +// zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.) +zara + +// zero : 2014-12-18 Amazon EU S.à r.l. +zero + +// zip : 2014-05-08 Charleston Road Registry Inc. +zip + +// zippo : 2015-07-02 Zadco Company +zippo + +// zone : 2013-11-14 Outer Falls, LLC +zone + +// zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich) +zuerich + + +// ===END ICANN DOMAINS=== +// ===BEGIN PRIVATE DOMAINS=== +// (Note: these are in alphabetical order by company name) + +// Alces Software Ltd : http://alces-software.com +// Submitted by Mark J. Titorenko +*.compute.estate +*.alces.network + +// Amazon CloudFront : https://aws.amazon.com/cloudfront/ +// Submitted by Donavan Miller +cloudfront.net + +// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/ +// Submitted by Luke Wells +ap-northeast-1.compute.amazonaws.com +ap-northeast-2.compute.amazonaws.com +ap-southeast-1.compute.amazonaws.com +ap-southeast-2.compute.amazonaws.com +cn-north-1.compute.amazonaws.cn +compute-1.amazonaws.com +compute.amazonaws.cn +compute.amazonaws.com +eu-central-1.compute.amazonaws.com +eu-west-1.compute.amazonaws.com +sa-east-1.compute.amazonaws.com +us-east-1.amazonaws.com +us-gov-west-1.compute.amazonaws.com +us-west-1.compute.amazonaws.com +us-west-2.compute.amazonaws.com +z-1.compute-1.amazonaws.com +z-2.compute-1.amazonaws.com + +// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ +// Submitted by Adam Stein +elasticbeanstalk.com + +// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ +// Submitted by Scott Vidmar +elb.amazonaws.com + +// Amazon S3 : https://aws.amazon.com/s3/ +// Submitted by Luke Wells +s3.amazonaws.com +s3-ap-northeast-1.amazonaws.com +s3-ap-northeast-2.amazonaws.com +s3-ap-southeast-1.amazonaws.com +s3-ap-southeast-2.amazonaws.com +s3-eu-central-1.amazonaws.com +s3-eu-west-1.amazonaws.com +s3-external-1.amazonaws.com +s3-external-2.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com +s3-sa-east-1.amazonaws.com +s3-us-gov-west-1.amazonaws.com +s3-us-west-1.amazonaws.com +s3-us-west-2.amazonaws.com +s3.ap-northeast-2.amazonaws.com +s3.cn-north-1.amazonaws.com.cn +s3.eu-central-1.amazonaws.com + +// Aptible : https://www.aptible.com/ +// Submitted by Thomas Orozco +on-aptible.com + +// AVM : https://avm.de +// Submitted by Andreas Weise +myfritz.net + +// BetaInABox +// Submitted by Adrian +betainabox.com + +// CentralNic : http://www.centralnic.com/names/domains +// Submitted by registry +ae.org +ar.com +br.com +cn.com +com.de +com.se +de.com +eu.com +gb.com +gb.net +hu.com +hu.net +jp.net +jpn.com +kr.com +mex.com +no.com +qc.com +ru.com +sa.com +se.com +se.net +uk.com +uk.net +us.com +uy.com +za.bz +za.com + +// Africa.com Web Solutions Ltd : https://registry.africa.com +// Submitted by Gavin Brown +africa.com + +// iDOT Services Limited : http://www.domain.gr.com +// Submitted by Gavin Brown +gr.com + +// Radix FZC : http://domains.in.net +// Submitted by Gavin Brown +in.net + +// US REGISTRY LLC : http://us.org +// Submitted by Gavin Brown +us.org + +// co.com Registry, LLC : https://registry.co.com +// Submitted by Gavin Brown +co.com + +// c.la : http://www.c.la/ +c.la + +// Citrix : https://citrix.com +// Submitted by Alex Stoddard +xenapponazure.com + +// cloudControl : https://www.cloudcontrol.com/ +// Submitted by Tobias Wilken +cloudcontrolled.com +cloudcontrolapp.com + +// co.ca : http://registry.co.ca/ +co.ca + +// i-registry s.r.o. : http://www.i-registry.cz/ +// Submitted by Martin Semrad +co.cz + +// CDN77.com : http://www.cdn77.com +// Submitted by Jan Krpes +c.cdn77.org +cdn77-ssl.net +r.cdn77.net +rsc.cdn77.org +ssl.origin.cdn77-secure.org + +// CoDNS B.V. +co.nl +co.no + +// Commerce Guys, SAS +// Submitted by Damien Tournoud +*.platform.sh + +// Cupcake : https://cupcake.io/ +// Submitted by Jonathan Rudenberg +cupcake.is + +// cyon GmbH : https://www.cyon.ch/ +// Submitted by Dominic Luechinger +cyon.link +cyon.site + +// Daplie, Inc : https://daplie.com +// Submitted by AJ ONeal +daplie.me + +// Dansk.net : http://www.dansk.net/ +// Submitted by Anani Voule +biz.dk +co.dk +firm.dk +reg.dk +store.dk + +// deSEC : https://desec.io/ +// Submitted by Peter Thomassen +dedyn.io + +// DNShome : https://www.dnshome.de/ +// Submitted by Norbert Auler +dnshome.de + +// DreamHost : http://www.dreamhost.com/ +// Submitted by Andrew Farmer +dreamhosters.com + +// Drobo : http://www.drobo.com/ +// Submitted by Ricardo Padilha +mydrobo.com + +// DuckDNS : http://www.duckdns.org/ +// Submitted by Richard Harper +duckdns.org + +// dy.fi : http://dy.fi/ +// Submitted by Heikki Hannikainen +dy.fi +tunk.org + +// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ +dyndns-at-home.com +dyndns-at-work.com +dyndns-blog.com +dyndns-free.com +dyndns-home.com +dyndns-ip.com +dyndns-mail.com +dyndns-office.com +dyndns-pics.com +dyndns-remote.com +dyndns-server.com +dyndns-web.com +dyndns-wiki.com +dyndns-work.com +dyndns.biz +dyndns.info +dyndns.org +dyndns.tv +at-band-camp.net +ath.cx +barrel-of-knowledge.info +barrell-of-knowledge.info +better-than.tv +blogdns.com +blogdns.net +blogdns.org +blogsite.org +boldlygoingnowhere.org +broke-it.net +buyshouses.net +cechire.com +dnsalias.com +dnsalias.net +dnsalias.org +dnsdojo.com +dnsdojo.net +dnsdojo.org +does-it.net +doesntexist.com +doesntexist.org +dontexist.com +dontexist.net +dontexist.org +doomdns.com +doomdns.org +dvrdns.org +dyn-o-saur.com +dynalias.com +dynalias.net +dynalias.org +dynathome.net +dyndns.ws +endofinternet.net +endofinternet.org +endoftheinternet.org +est-a-la-maison.com +est-a-la-masion.com +est-le-patron.com +est-mon-blogueur.com +for-better.biz +for-more.biz +for-our.info +for-some.biz +for-the.biz +forgot.her.name +forgot.his.name +from-ak.com +from-al.com +from-ar.com +from-az.net +from-ca.com +from-co.net +from-ct.com +from-dc.com +from-de.com +from-fl.com +from-ga.com +from-hi.com +from-ia.com +from-id.com +from-il.com +from-in.com +from-ks.com +from-ky.com +from-la.net +from-ma.com +from-md.com +from-me.org +from-mi.com +from-mn.com +from-mo.com +from-ms.com +from-mt.com +from-nc.com +from-nd.com +from-ne.com +from-nh.com +from-nj.com +from-nm.com +from-nv.com +from-ny.net +from-oh.com +from-ok.com +from-or.com +from-pa.com +from-pr.com +from-ri.com +from-sc.com +from-sd.com +from-tn.com +from-tx.com +from-ut.com +from-va.com +from-vt.com +from-wa.com +from-wi.com +from-wv.com +from-wy.com +ftpaccess.cc +fuettertdasnetz.de +game-host.org +game-server.cc +getmyip.com +gets-it.net +go.dyndns.org +gotdns.com +gotdns.org +groks-the.info +groks-this.info +ham-radio-op.net +here-for-more.info +hobby-site.com +hobby-site.org +home.dyndns.org +homedns.org +homeftp.net +homeftp.org +homeip.net +homelinux.com +homelinux.net +homelinux.org +homeunix.com +homeunix.net +homeunix.org +iamallama.com +in-the-band.net +is-a-anarchist.com +is-a-blogger.com +is-a-bookkeeper.com +is-a-bruinsfan.org +is-a-bulls-fan.com +is-a-candidate.org +is-a-caterer.com +is-a-celticsfan.org +is-a-chef.com +is-a-chef.net +is-a-chef.org +is-a-conservative.com +is-a-cpa.com +is-a-cubicle-slave.com +is-a-democrat.com +is-a-designer.com +is-a-doctor.com +is-a-financialadvisor.com +is-a-geek.com +is-a-geek.net +is-a-geek.org +is-a-green.com +is-a-guru.com +is-a-hard-worker.com +is-a-hunter.com +is-a-knight.org +is-a-landscaper.com +is-a-lawyer.com +is-a-liberal.com +is-a-libertarian.com +is-a-linux-user.org +is-a-llama.com +is-a-musician.com +is-a-nascarfan.com +is-a-nurse.com +is-a-painter.com +is-a-patsfan.org +is-a-personaltrainer.com +is-a-photographer.com +is-a-player.com +is-a-republican.com +is-a-rockstar.com +is-a-socialist.com +is-a-soxfan.org +is-a-student.com +is-a-teacher.com +is-a-techie.com +is-a-therapist.com +is-an-accountant.com +is-an-actor.com +is-an-actress.com +is-an-anarchist.com +is-an-artist.com +is-an-engineer.com +is-an-entertainer.com +is-by.us +is-certified.com +is-found.org +is-gone.com +is-into-anime.com +is-into-cars.com +is-into-cartoons.com +is-into-games.com +is-leet.com +is-lost.org +is-not-certified.com +is-saved.org +is-slick.com +is-uberleet.com +is-very-bad.org +is-very-evil.org +is-very-good.org +is-very-nice.org +is-very-sweet.org +is-with-theband.com +isa-geek.com +isa-geek.net +isa-geek.org +isa-hockeynut.com +issmarterthanyou.com +isteingeek.de +istmein.de +kicks-ass.net +kicks-ass.org +knowsitall.info +land-4-sale.us +lebtimnetz.de +leitungsen.de +likes-pie.com +likescandy.com +merseine.nu +mine.nu +misconfused.org +mypets.ws +myphotos.cc +neat-url.com +office-on-the.net +on-the-web.tv +podzone.net +podzone.org +readmyblog.org +saves-the-whales.com +scrapper-site.net +scrapping.cc +selfip.biz +selfip.com +selfip.info +selfip.net +selfip.org +sells-for-less.com +sells-for-u.com +sells-it.net +sellsyourhome.org +servebbs.com +servebbs.net +servebbs.org +serveftp.net +serveftp.org +servegame.org +shacknet.nu +simple-url.com +space-to-rent.com +stuff-4-sale.org +stuff-4-sale.us +teaches-yoga.com +thruhere.net +traeumtgerade.de +webhop.biz +webhop.info +webhop.net +webhop.org +worse-than.tv +writesthisblog.com + +// dynv6 : https://dynv6.com +// Submitted by Dominik Menke 2016-01-18 +dynv6.net + +// E4YOU spol. s.r.o. : https://e4you.cz/ +// Submitted by Vladimir Dudr +e4.cz + +// EU.org https://eu.org/ +// Submitted by Pierre Beyssac +eu.org +al.eu.org +asso.eu.org +at.eu.org +au.eu.org +be.eu.org +bg.eu.org +ca.eu.org +cd.eu.org +ch.eu.org +cn.eu.org +cy.eu.org +cz.eu.org +de.eu.org +dk.eu.org +edu.eu.org +ee.eu.org +es.eu.org +fi.eu.org +fr.eu.org +gr.eu.org +hr.eu.org +hu.eu.org +ie.eu.org +il.eu.org +in.eu.org +int.eu.org +is.eu.org +it.eu.org +jp.eu.org +kr.eu.org +lt.eu.org +lu.eu.org +lv.eu.org +mc.eu.org +me.eu.org +mk.eu.org +mt.eu.org +my.eu.org +net.eu.org +ng.eu.org +nl.eu.org +no.eu.org +nz.eu.org +paris.eu.org +pl.eu.org +pt.eu.org +q-a.eu.org +ro.eu.org +ru.eu.org +se.eu.org +si.eu.org +sk.eu.org +tr.eu.org +uk.eu.org +us.eu.org + +// Facebook, Inc. +// Submitted by Peter Ruibal +apps.fbsbx.com + +// Fastly Inc. http://www.fastly.com/ +// Submitted by Vladimir Vuksan +a.ssl.fastly.net +b.ssl.fastly.net +global.ssl.fastly.net +a.prod.fastly.net +global.prod.fastly.net + +// Firebase, Inc. +// Submitted by Chris Raynor +firebaseapp.com + +// Flynn : https://flynn.io +// Submitted by Jonathan Rudenberg +flynnhub.com + +// Freebox : http://www.freebox.fr +// Submitted by Romain Fliedel +freebox-os.com +freeboxos.com +fbx-os.fr +fbxos.fr +freebox-os.fr +freeboxos.fr + +// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains +// Submitted by David Illsley +service.gov.uk + +// GitHub, Inc. +// Submitted by Patrick Toomey +github.io +githubusercontent.com +githubcloud.com +*.api.githubcloud.com +*.ext.githubcloud.com +gist.githubcloud.com +*.githubcloudusercontent.com + +// GlobeHosting, Inc. +// Submitted by Zoltan Egresi +ro.com + +// GoIP DNS Services : http://www.goip.de +// Submitted by Christian Poulter +goip.de + +// Google, Inc. +// Submitted by Eduardo Vela +*.0emm.com +appspot.com +blogspot.ae +blogspot.al +blogspot.am +blogspot.ba +blogspot.be +blogspot.bg +blogspot.bj +blogspot.ca +blogspot.cf +blogspot.ch +blogspot.cl +blogspot.co.at +blogspot.co.id +blogspot.co.il +blogspot.co.ke +blogspot.co.nz +blogspot.co.uk +blogspot.co.za +blogspot.com +blogspot.com.ar +blogspot.com.au +blogspot.com.br +blogspot.com.by +blogspot.com.co +blogspot.com.cy +blogspot.com.ee +blogspot.com.eg +blogspot.com.es +blogspot.com.mt +blogspot.com.ng +blogspot.com.tr +blogspot.com.uy +blogspot.cv +blogspot.cz +blogspot.de +blogspot.dk +blogspot.fi +blogspot.fr +blogspot.gr +blogspot.hk +blogspot.hr +blogspot.hu +blogspot.ie +blogspot.in +blogspot.is +blogspot.it +blogspot.jp +blogspot.kr +blogspot.li +blogspot.lt +blogspot.lu +blogspot.md +blogspot.mk +blogspot.mr +blogspot.mx +blogspot.my +blogspot.nl +blogspot.no +blogspot.pe +blogspot.pt +blogspot.qa +blogspot.re +blogspot.ro +blogspot.rs +blogspot.ru +blogspot.se +blogspot.sg +blogspot.si +blogspot.sk +blogspot.sn +blogspot.td +blogspot.tw +blogspot.ug +blogspot.vn +cloudfunctions.net +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +withgoogle.com +withyoutube.com + +// Hashbang : https://hashbang.sh +hashbang.sh + +// Heroku : https://www.heroku.com/ +// Submitted by Tom Maher +herokuapp.com +herokussl.com + +// iki.fi +// Submitted by Hannu Aronsson +iki.fi + +// info.at : http://www.info.at/ +biz.at +info.at + +// Michau Enterprises Limited : http://www.co.pl/ +co.pl + +// Microsoft : http://microsoft.com +// Submitted by Barry Dorrans +azurewebsites.net +azure-mobile.net +cloudapp.net + +// Mozilla Foundation : https://mozilla.org/ +// Submitted by glob +bmoattachments.org + +// Neustar Inc. +// Submitted by Trung Tran +4u.com + +// ngrok : https://ngrok.com/ +// Submitted by Alan Shreve +ngrok.io + +// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ +// Submitted by Jeff Wheelhouse +nfshost.com + +// nsupdate.info : https://www.nsupdate.info/ +// Submitted by Thomas Waldmann +nsupdate.info +nerdpol.ovh + +// No-IP.com : https://noip.com/ +// Submitted by Deven Reza +blogsyte.com +brasilia.me +cable-modem.org +ciscofreak.com +collegefan.org +couchpotatofries.org +damnserver.com +ddns.me +ditchyourip.com +dnsfor.me +dnsiskinky.com +dvrcam.info +dynns.com +eating-organic.net +fantasyleague.cc +geekgalaxy.com +golffan.us +health-carereform.com +homesecuritymac.com +homesecuritypc.com +hopto.me +ilovecollege.info +loginto.me +mlbfan.org +mmafan.biz +myactivedirectory.com +mydissent.net +myeffect.net +mymediapc.net +mypsx.net +mysecuritycamera.com +mysecuritycamera.net +mysecuritycamera.org +net-freaks.com +nflfan.org +nhlfan.net +no-ip.ca +no-ip.co.uk +no-ip.net +noip.us +onthewifi.com +pgafan.net +point2this.com +pointto.us +privatizehealthinsurance.net +quicksytes.com +read-books.org +securitytactics.com +serveexchange.com +servehumour.com +servep2p.com +servesarcasm.com +stufftoread.com +ufcfan.org +unusualperson.com +workisboring.com +3utilities.com +bounceme.net +ddns.net +ddnsking.com +gotdns.ch +hopto.org +myftp.biz +myftp.org +myvnc.com +no-ip.biz +no-ip.info +no-ip.org +noip.me +redirectme.net +servebeer.com +serveblog.net +servecounterstrike.com +serveftp.com +servegame.com +servehalflife.com +servehttp.com +serveirc.com +serveminecraft.net +servemp3.com +servepics.com +servequake.com +sytes.net +webhop.me +zapto.org + +// NYC.mn : http://www.information.nyc.mn +// Submitted by Matthew Brown +nyc.mn + +// One Fold Media : http://www.onefoldmedia.com/ +// Submitted by Eddie Jones +nid.io + +// Opera Software, A.S.A. +// Submitted by Yngve Pettersen +operaunite.com + +// OutSystems +// Submitted by Duarte Santos +outsystemscloud.com + +// OwnProvider : http://www.ownprovider.com +// Submitted by Jan Moennich +ownprovider.com + +// oy.lc +// Submitted by Charly Coste +oy.lc + +// Pagefog : https://pagefog.com/ +// Submitted by Derek Myers +pgfog.com + +// Pagefront : https://www.pagefronthq.com/ +// Submitted by Jason Kriss +pagefrontapp.com + +// .pl domains (grandfathered) +art.pl +gliwice.pl +krakow.pl +poznan.pl +wroc.pl +zakopane.pl + +// Pantheon Systems, Inc. : https://pantheon.io/ +// Submitted by Gary Dylina +pantheonsite.io +gotpantheon.com + +// Peplink | Pepwave : http://peplink.com/ +// Submitted by Steve Leung +mypep.link + +// prgmr.com : https://prgmr.com/ +// Submitted by Sarah Newman +xen.prgmr.com + +// priv.at : http://www.nic.priv.at/ +// Submitted by registry +priv.at + +// Publication Presse Communication SARL : https://ppcom.fr +// Submitted by Yaacov Akiba Slama +chirurgiens-dentistes-en-france.fr + +// QA2 +// Submitted by Daniel Dent (https://www.danieldent.com/) +qa2.com + +// Rackmaze LLC : https://www.rackmaze.com +// Submitted by Kirill Pertsev +rackmaze.com +rackmaze.net + +// Red Hat, Inc. OpenShift : https://openshift.redhat.com/ +// Submitted by Tim Kramer +rhcloud.com + +// RethinkDB : https://www.rethinkdb.com/ +// Submitted by Chris Kastorff +hzc.io + +// Sandstorm Development Group, Inc. : https://sandcats.io/ +// Submitted by Asheesh Laroia +sandcats.io + +// Service Online LLC : http://drs.ua/ +// Submitted by Serhii Bulakh +biz.ua +co.ua +pp.ua + +// SinaAppEngine : http://sae.sina.com.cn/ +// Submitted by SinaAppEngine +sinaapp.com +vipsinaapp.com +1kapp.com + +// Skyhat : http://www.skyhat.io +// Submitted by Shante Adam +bounty-full.com +alpha.bounty-full.com +beta.bounty-full.com + +// SpaceKit : https://www.spacekit.io/ +// Submitted by Reza Akhavan +spacekit.io + +// Synology, Inc. : https://www.synology.com/ +// Submitted by Rony Weng +diskstation.me +dscloud.biz +dscloud.me +dscloud.mobi +dsmynas.com +dsmynas.net +dsmynas.org +familyds.com +familyds.net +familyds.org +i234.me +myds.me +synology.me + +// TASK geographical domains (www.task.gda.pl/uslugi/dns) +gda.pl +gdansk.pl +gdynia.pl +med.pl +sopot.pl + +// TownNews.com domains : http://www.townnews.com +// Submitted by Dustin Ward +bloxcms.com +townnews-staging.com + +// UDR Limited : http://www.udr.hk.com +// Submitted by registry +hk.com +hk.org +ltd.hk +inc.hk + +// Viprinet Europe GmbH : http://www.viprinet.com +// Submitted by Simon Kissel +router.management + +// Yola : https://www.yola.com/ +// Submitted by Stefano Rivera +yolasite.com + +// ZaNiC : http://www.za.net/ +// Submitted by registry +za.net +za.org + +// ===END PRIVATE DOMAINS=== diff --git a/scripts/update-oembed.php b/scripts/update-oembed.php new file mode 100644 index 00000000..3bfca812 --- /dev/null +++ b/scripts/update-oembed.php @@ -0,0 +1,54 @@ +provider_name; + $url = $provider->provider_url; + + foreach ($provider->endpoints as $endpoint) { + saveEndpoint($endpoint->url, $endpoint->schemes ?? ["$url*"]); + } +} + +//Export the endpoints +file_put_contents( + dirname(__DIR__).'/src/resources/oembed.php', + sprintf(" $line[0] !== '/'); + +file_put_contents( + dirname(__DIR__).'/src/resources/suffix.php', + sprintf(" 16, - 'minImageHeight' => 16, - 'imagesBlacklist' => null, - 'getBiggerImage' => false, - 'getBiggerIcon' => false, - ]; - - /** - * {@inheritdoc} - */ - public function __construct(Request $request, array $config = null) - { - $this->request = $request; - - if (isset($config['adapter']['config'])) { - $this->config = array_replace($this->config, $config['adapter']['config']); - } - - if (isset($config['providers'])) { - $this->providersConfig = $config['providers']; - } - - if (isset($config['image']['class'])) { - $this->imageClass = $config['image']['class']; - } - - if (isset($config['image']['config'])) { - $this->imageConfig = $config['image']['config']; - } - - $this->init(); - } - - /** - * Init the adapter. - */ - protected function init() - { - $this->run(); - - //if the canonical url is different, repeat the proccess - $canonical = $this->getUrl(); - - if ($this->request->getUrl() !== $canonical) { - $request = $this->request->withUrl($canonical); - - if ($request->isValid()) { - $this->request = $request; - $this->run(); - } - } - } - - /** - * Run the adapter. - */ - abstract protected function run(); - - /** - * {@inheritdoc} - */ - public function getRequest() - { - return $this->request; - } - - /** - * Adds a new provider. - * - * @param string $name - * @param ProviderInterface $provider - */ - protected function addProvider($name, ProviderInterface $provider) - { - $config = isset($this->providersConfig[$name]) ? $this->providersConfig[$name] : null; - - $provider->init($this->request, $config); - $provider->run(); - - $this->providers[$name] = $provider; - } - - /** - * {@inheritdoc} - */ - public function getProvider($name) - { - return isset($this->providers[$name]) ? $this->providers[$name] : null; - } - - /** - * {@inheritdoc} - */ - public function getAllProviders() - { - return $this->providers; - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return html_entity_decode(Utils::getFirstValue(Utils::getData($this->providers, 'title')) ?: $this->request->getUrl()); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return html_entity_decode(Utils::getFirstValue(Utils::getData($this->providers, 'description'))); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - $code = $this->code; - - if (strpos($code, '')) { - return 'video'; - } - - if (($type = Utils::getMostPopularValue(Utils::getData($this->providers, 'type'))) && ($type !== 'link')) { - return $type; - } - - if (empty($code)) { - return 'link'; - } - - if (strpos($code, '') || strpos($code, '') || strpos($code, '') || strpos($code, '')) { - return 'rich'; - } - - return 'link'; - } - - /** - * {@inheritdoc} - */ - public function getTags() - { - return Utils::getAllValues(Utils::getData($this->providers, 'tags')); - } - - /** - * {@inheritdoc} - */ - public function getSource() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'source', $this->request)); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $this->width = null; - $this->height = null; - $choosen = null; - - foreach (Utils::getData($this->providers, 'code') as $code) { - // and codes have less priority - if (strpos($code['value'], '') !== false || strpos($code['value'], '') !== false) { - if (empty($choosen)) { - $choosen = $code; - } - - continue; - } - - if (strpos($code['value'], '') !== false) { - $code['value'] = preg_replace('|^.*().*$|Us', '$1', $code['value']); - } - - $choosen = $code; - break; - } - - if ($choosen) { - //get the width/height - foreach ($choosen['providers'] as $provider) { - $this->width = $this->providers[$provider]->getWidth(); - $this->height = $this->providers[$provider]->getHeight(); - - if (is_numeric($this->width)) { - $this->width = (int) $this->width; - } - - if (is_numeric($this->height)) { - $this->height = (int) $this->height; - } - - if (!empty($this->width) || !empty($this->height)) { - break; - } - } - - return $choosen['value']; - } - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'url', $this->request)) ?: $this->request->getUrl(); - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'authorName')); - } - - /** - * {@inheritdoc} - */ - public function getAuthorUrl() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'authorUrl', $this->request)); - } - - /** - * {@inheritdoc} - */ - public function getProviderIconsUrls() - { - $icons = Utils::getData($this->providers, 'providerIconsUrls', $this->request); - - Utils::unshiftValue($icons, [ - 'value' => $this->request->getAbsolute('/favicon.ico'), - 'providers' => ['adapter'], - ]); - - Utils::unshiftValue($icons, [ - 'value' => $this->request->getAbsolute('/favicon.png'), - 'providers' => ['adapter'], - ]); - - return $icons; - } - - /** - * {@inheritdoc} - */ - public function getProviderIcons() - { - return call_user_func("{$this->imageClass}::getImagesInfo", $this->getProviderIconsUrls(), $this->imageConfig); - } - - /** - * {@inheritdoc} - */ - public function getProviderIcon() - { - if ($this->config['getBiggerIcon']) { - return Utils::getBiggerValue($this->providerIcons); - } - - return Utils::getFirstValue($this->providerIcons); - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'providerName')) ?: $this->request->getDomain(); - } - - /** - * {@inheritdoc} - */ - public function getProviderUrl() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'providerUrl', $this->request)) ?: ($this->request->getScheme().'://'.$this->request->getDomain(true)); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $imagesUrls = Utils::getData($this->providers, 'imagesUrls', $this->request); - - $blacklist = $this->config['imagesBlacklist']; - $hasBlacklist = is_array($blacklist) && count($blacklist) > 0; - - $imagesUrls = array_filter($imagesUrls, function ($imageUrl) use ($blacklist, $hasBlacklist) { - // Clean empty urls - if (empty($imageUrl['value'])) { - return false; - } - - // Remove image url if on blacklist - if ($hasBlacklist) { - $url = new Url($imageUrl['value']); - - return !$url->match($blacklist) && !in_array($imageUrl['value'], $blacklist, true); - } - - return true; - }); - - // Use array_values to reset keys after filter - return array_values($imagesUrls); - } - - /** - * {@inheritdoc} - */ - public function getImages() - { - return call_user_func("{$this->imageClass}::getImagesInfo", $this->getImagesUrls(), $this->imageConfig); - } - - /** - * {@inheritdoc} - */ - public function getImage() - { - if ($this->config['getBiggerImage']) { - $allImages = $this->images; - - if (empty($allImages)) { - return; - } - - $allImages = [$allImages]; - } else { - $allImages = Utils::sortByProviders($this->images); - } - - foreach ($allImages as $images) { - if (($key = Utils::getBiggerValue($images, true)) !== null) { - $image = $images[$key]; - - if (($image['width'] >= $this->config['minImageWidth']) && ($image['height'] >= $this->config['minImageHeight'])) { - return $image['value']; - } - } - } - } - - /** - * {@inheritdoc} - */ - public function getImageWidth() - { - if (($image = Utils::searchValue($this->images, $this->image)) !== false) { - return $image['width']; - } - } - - /** - * {@inheritdoc} - */ - public function getImageHeight() - { - if (($image = Utils::searchValue($this->images, $this->image)) !== false) { - return $image['height']; - } - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - $this->__get('code'); - - return $this->width; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - $this->__get('code'); - - return $this->height; - } - - /** - * {@inheritdoc} - */ - public function getAspectRatio() - { - if ($this->width && (strpos($this->width, '%') === false) && $this->height && (strpos($this->height, '%') === false)) { - return round(($this->height / $this->width) * 100, 3); - } - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - return Utils::getFirstValue(Utils::getData($this->providers, 'publishedTime')); - } -} diff --git a/src/Adapters/AdapterInterface.php b/src/Adapters/AdapterInterface.php deleted file mode 100644 index 41169e27..00000000 --- a/src/Adapters/AdapterInterface.php +++ /dev/null @@ -1,107 +0,0 @@ -isValid() && $request->match([ - 'https?://archive.org/details/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('archive', new Api\Archive()); - - parent::run(); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - return Utils::iframe(str_replace('/details/', '/embed/', $this->getUrl()), $this->getWidth(), $this->getHeight()); - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return 640; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return 480; - } -} diff --git a/src/Adapters/Archive/Api.php b/src/Adapters/Archive/Api.php new file mode 100644 index 00000000..b4820eaa --- /dev/null +++ b/src/Adapters/Archive/Api.php @@ -0,0 +1,21 @@ + + */ + protected function fetchData(): array + { + $this->endpoint = $this->extractor->getUri()->withQuery('output=json'); + + return $this->fetchJSON($this->endpoint); + } +} diff --git a/src/Adapters/Archive/Detectors/AuthorName.php b/src/Adapters/Archive/Detectors/AuthorName.php new file mode 100644 index 00000000..a58abfbc --- /dev/null +++ b/src/Adapters/Archive/Detectors/AuthorName.php @@ -0,0 +1,20 @@ + + */ +class AuthorName extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('metadata', 'creator'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Archive/Detectors/Code.php b/src/Adapters/Archive/Detectors/Code.php new file mode 100644 index 00000000..e5888c57 --- /dev/null +++ b/src/Adapters/Archive/Detectors/Code.php @@ -0,0 +1,40 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + $path = $uri->getPath(); + + if (!matchPath('/details/*', $path)) { + return null; + } + + $src = $uri->withPath(str_replace('/details/', '/embed/', $path)); + $width = 640; + $height = 480; + + $html = html('iframe', [ + 'src' => $src, + 'width' => $width, + 'height' => $height, + 'style' => 'border:none', + 'frameborder' => 0, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, $width, $height); + } +} diff --git a/src/Adapters/Archive/Detectors/Description.php b/src/Adapters/Archive/Detectors/Description.php new file mode 100644 index 00000000..b9553044 --- /dev/null +++ b/src/Adapters/Archive/Detectors/Description.php @@ -0,0 +1,20 @@ + + */ +class Description extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('metadata', 'extract'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Archive/Detectors/ProviderName.php b/src/Adapters/Archive/Detectors/ProviderName.php new file mode 100644 index 00000000..4f036c27 --- /dev/null +++ b/src/Adapters/Archive/Detectors/ProviderName.php @@ -0,0 +1,17 @@ + + */ +class ProviderName extends Detector +{ + public function detect(): string + { + return 'Internet Archive'; + } +} diff --git a/src/Adapters/Archive/Detectors/PublishedTime.php b/src/Adapters/Archive/Detectors/PublishedTime.php new file mode 100644 index 00000000..c2f76aec --- /dev/null +++ b/src/Adapters/Archive/Detectors/PublishedTime.php @@ -0,0 +1,28 @@ + + */ +class PublishedTime extends Detector +{ + public function detect(): ?DateTime + { + $api = $this->extractor->getApi(); + + $fields = ['publicdate', 'addeddate', 'date']; + foreach ($fields as $field) { + $result = $api->time('metadata', $field); + if ($result !== null) { + return $result; + } + } + + return parent::detect(); + } +} diff --git a/src/Adapters/Archive/Detectors/Title.php b/src/Adapters/Archive/Detectors/Title.php new file mode 100644 index 00000000..a5b83eb1 --- /dev/null +++ b/src/Adapters/Archive/Detectors/Title.php @@ -0,0 +1,20 @@ + + */ +class Title extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('metadata', 'title'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Archive/Extractor.php b/src/Adapters/Archive/Extractor.php new file mode 100644 index 00000000..482e13a9 --- /dev/null +++ b/src/Adapters/Archive/Extractor.php @@ -0,0 +1,45 @@ +> + */ +class Extractor extends Base +{ + private Api $api; + + public function __construct( + UriInterface $uri, + RequestInterface $request, + ResponseInterface $response, + Crawler $crawler + ) { + parent::__construct($uri, $request, $response, $crawler); + $this->api = new Api($this); + } + + public function getApi(): Api + { + return $this->api; + } + + public function createCustomDetectors(): array + { + return [ + 'title' => new Detectors\Title($this), + 'description' => new Detectors\Description($this), + 'code' => new Detectors\Code($this), + 'authorName' => new Detectors\AuthorName($this), + 'providerName' => new Detectors\ProviderName($this), + 'publishedTime' => new Detectors\PublishedTime($this), + ]; + } +} diff --git a/src/Adapters/Bandcamp/Detectors/ProviderName.php b/src/Adapters/Bandcamp/Detectors/ProviderName.php new file mode 100644 index 00000000..a52c98a8 --- /dev/null +++ b/src/Adapters/Bandcamp/Detectors/ProviderName.php @@ -0,0 +1,17 @@ + + */ +class ProviderName extends Detector +{ + public function detect(): string + { + return 'Bandcamp'; + } +} diff --git a/src/Adapters/Bandcamp/Extractor.php b/src/Adapters/Bandcamp/Extractor.php new file mode 100644 index 00000000..94e03537 --- /dev/null +++ b/src/Adapters/Bandcamp/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'providerName' => new Detectors\ProviderName($this), + ]; + } +} diff --git a/src/Adapters/CadenaSer/Detectors/Code.php b/src/Adapters/CadenaSer/Detectors/Code.php new file mode 100644 index 00000000..bf70e664 --- /dev/null +++ b/src/Adapters/CadenaSer/Detectors/Code.php @@ -0,0 +1,44 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/audio/*', $uri->getPath())) { + return null; + } + + $path = cleanPath('/widget/'.$uri->getPath()); + $src = $uri->withPath($path); + + $html = html('iframe', [ + 'src' => $src, + 'frameborder' => 0, + 'width' => '100%', + 'height' => '360', + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, null, 360); + } +} diff --git a/src/Adapters/CadenaSer/Extractor.php b/src/Adapters/CadenaSer/Extractor.php new file mode 100644 index 00000000..e6d05ef6 --- /dev/null +++ b/src/Adapters/CadenaSer/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Facebook.php b/src/Adapters/Facebook.php deleted file mode 100644 index 4d412672..00000000 --- a/src/Adapters/Facebook.php +++ /dev/null @@ -1,32 +0,0 @@ -isValid() && $request->match([ - 'https://www.facebook.com/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('facebook', new Api\Facebook()); - - parent::run(); - } -} diff --git a/src/Adapters/Facebook/Detectors/Title.php b/src/Adapters/Facebook/Detectors/Title.php new file mode 100644 index 00000000..298d2631 --- /dev/null +++ b/src/Adapters/Facebook/Detectors/Title.php @@ -0,0 +1,24 @@ + + */ +class Title extends Detector +{ + /** + * Do not use og:title and twitter:title + */ + public function detect(): ?string + { + $document = $this->extractor->getDocument(); + $oembed = $this->extractor->getOEmbed(); + + $result = $oembed->str('title'); + return $result !== null ? $result : $document->select('.//head/title')->str(); + } +} diff --git a/src/Adapters/Facebook/Extractor.php b/src/Adapters/Facebook/Extractor.php new file mode 100644 index 00000000..9b8e4fdb --- /dev/null +++ b/src/Adapters/Facebook/Extractor.php @@ -0,0 +1,21 @@ +oembed = new OEmbed($this); + + return [ + 'title' => new Detectors\Title($this), + ]; + } +} diff --git a/src/Adapters/Facebook/OEmbed.php b/src/Adapters/Facebook/OEmbed.php new file mode 100644 index 00000000..075b0bdf --- /dev/null +++ b/src/Adapters/Facebook/OEmbed.php @@ -0,0 +1,80 @@ +extractor->getSetting('facebook:token'); + + if (!is_string($token) || $token === '') { + return null; + } + + $uri = $this->extractor->getUri(); + if (strpos($uri->getPath(), 'login') !== false) { + parse_str($uri->getQuery(), $params); + if (isset($params['next']) && is_string($params['next']) && $params['next'] !== '' && $params['next'] !== '0') { + $uri = $this->extractor->getCrawler()->createUri($params['next']); + } + } + $queryParameters = $this->getOembedQueryParameters((string) $uri); + $queryParameters['access_token'] = $token; + + return $this->extractor->getCrawler() + ->createUri($this->getEndpointByPath($uri->getPath())) + ->withQuery(http_build_query($queryParameters)); + } + + private function getEndpointByPath(string $path): string + { + /* Videos + https://www.facebook.com/{page-name}/videos/{video-id}/ + https://www.facebook.com/{username}/videos/{video-id}/ + https://www.facebook.com/video.php?id={video-id} + https://www.facebook.com/video.php?v={video-id} + */ + if (strpos($path, '/video.php') === 0 + || strpos($path, '/videos/') !== false + ) { + return self::ENDPOINT_VIDEO; + } + + /* Posts + https://www.facebook.com/{page-name}/posts/{post-id} + https://www.facebook.com/{username}/posts/{post-id} + https://www.facebook.com/{username}/activity/{activity-id} + https://www.facebook.com/photo.php?fbid={photo-id} + https://www.facebook.com/photos/{photo-id} + https://www.facebook.com/permalink.php?story_fbid={post-id} + https://www.facebook.com/media/set?set={set-id} + https://www.facebook.com/questions/{question-id} + https://www.facebook.com/notes/{username}/{note-url}/{note-id} + + Not in the facebook docs: + https://www.facebook.com/{page-name}/photos/{post-id}/{photo-id} + */ + if (strpos($path, '/photo.php') === 0 + || strpos($path, '/photos/') !== false + || strpos($path, '/permalink.php') === 0 + || strpos($path, '/media/') === 0 + || strpos($path, '/questions/') === 0 + || strpos($path, '/notes/') === 0 + || strpos($path, '/posts/') !== false + || strpos($path, '/activity/') !== false + ) { + return self::ENDPOINT_POST; + } + + return self::ENDPOINT_PAGE; + } +} diff --git a/src/Adapters/File.php b/src/Adapters/File.php deleted file mode 100644 index 33c02fea..00000000 --- a/src/Adapters/File.php +++ /dev/null @@ -1,100 +0,0 @@ - ['video', 'videoHtml'], - 'application/ogg' => ['video', 'videoHtml'], - 'video/ogv' => ['video', 'videoHtml'], - 'video/webm' => ['video', 'videoHtml'], - 'video/mp4' => ['video', 'videoHtml'], - 'audio/ogg' => ['audio', 'audioHtml'], - 'audio/mp3' => ['audio', 'audioHtml'], - 'audio/mpeg' => ['audio', 'audioHtml'], - 'audio/webm' => ['audio', 'audioHtml'], - 'image/jpeg' => ['photo', 'imageHtml'], - 'image/gif' => ['photo', 'imageHtml'], - 'image/png' => ['photo', 'imageHtml'], - 'image/bmp' => ['photo', 'imageHtml'], - 'image/ico' => ['photo', 'imageHtml'], - 'text/rtf' => ['rich', 'google'], - 'application/pdf' => ['rich', 'google'], - 'application/msword' => ['rich', 'google'], - 'application/vnd.ms-powerpoint' => ['rich', 'google'], - 'application/vnd.ms-excel' => ['rich', 'google'], - 'application/zip' => ['rich', 'google'], - 'application/postscript' => ['rich', 'google'], - 'application/octet-stream' => ['rich', 'google'], - ]; - - /** - * {@inheritdoc} - */ - public static function check(Request $request) - { - return $request->isValid() && isset(self::$contentTypes[$request->getMimeType()]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('oembed', new Providers\OEmbed()); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return self::$contentTypes[$this->request->getMimeType()][0]; - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if (($code = parent::getcode())) { - return $code; - } - - switch (self::$contentTypes[$this->request->getMimeType()][1]) { - case 'videoHtml': - return Utils::videoHtml($this->image, $this->url, $this->imageWidth, $this->imageHeight); - - case 'audioHtml': - return Utils::audioHtml($this->url); - - case 'google': - return Utils::google($this->url); - } - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - if ($this->type === 'photo') { - return [ - [ - 'value' => $this->url, - 'providers' => ['adapter'], - ], - ]; - } - - return []; - } -} diff --git a/src/Adapters/Flickr.php b/src/Adapters/Flickr.php deleted file mode 100644 index 36050935..00000000 --- a/src/Adapters/Flickr.php +++ /dev/null @@ -1,68 +0,0 @@ -isValid() && $request->match([ - 'https://www.flickr.com/photos/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $code = parent::getCode(); - - if (empty($code)) { - $code = Utils::iframe($this->request->createUrl()->withAddedPath('player'), $this->width, $this->height); - } - - return $code; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - if (!parent::getCode()) { - return 640; - } - - return parent::getWidth(); - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - if (!parent::getCode()) { - return 425; - } - - return parent::getHeight(); - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return 'Flickr'; - } -} diff --git a/src/Adapters/Flickr/Detectors/Code.php b/src/Adapters/Flickr/Detectors/Code.php new file mode 100644 index 00000000..9f14eb19 --- /dev/null +++ b/src/Adapters/Flickr/Detectors/Code.php @@ -0,0 +1,51 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + if ($result !== null) { + return $result; + } + + return $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/photos/*', $uri->getPath())) { + return null; + } + + $path = cleanPath($uri->getPath().'/player'); + $src = $uri->withPath($path); + $width = 640; + $height = 425; + + $html = html('iframe', [ + 'src' => $src, + 'width' => $width, + 'height' => $height, + 'style' => 'border:none', + 'frameborder' => 0, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, $width, $height); + } +} diff --git a/src/Adapters/Flickr/Extractor.php b/src/Adapters/Flickr/Extractor.php new file mode 100644 index 00000000..0a4369c8 --- /dev/null +++ b/src/Adapters/Flickr/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Gist/Api.php b/src/Adapters/Gist/Api.php new file mode 100644 index 00000000..b8262d24 --- /dev/null +++ b/src/Adapters/Gist/Api.php @@ -0,0 +1,22 @@ + + */ + protected function fetchData(): array + { + $uri = $this->extractor->getUri(); + $this->endpoint = $uri->withPath($uri->getPath().'.json'); + + return $this->fetchJSON($this->endpoint); + } +} diff --git a/src/Adapters/Gist/Detectors/AuthorName.php b/src/Adapters/Gist/Detectors/AuthorName.php new file mode 100644 index 00000000..a4566624 --- /dev/null +++ b/src/Adapters/Gist/Detectors/AuthorName.php @@ -0,0 +1,20 @@ + + */ +class AuthorName extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('owner'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Gist/Detectors/AuthorUrl.php b/src/Adapters/Gist/Detectors/AuthorUrl.php new file mode 100644 index 00000000..d9bae2a8 --- /dev/null +++ b/src/Adapters/Gist/Detectors/AuthorUrl.php @@ -0,0 +1,28 @@ + + */ +class AuthorUrl extends Detector +{ + public function detect(): ?UriInterface + { + $extractor = $this->extractor; + $api = $extractor->getApi(); + $owner = $api->str('owner'); + + // Exclude empty string and '0' to maintain original truthy check behavior + // The string '0' is not a valid GitHub username and should not generate a URL + if (is_string($owner) && $owner !== '' && $owner !== '0') { + return $extractor->getCrawler()->createUri("https://github.com/%7B$owner%7D"); + } + + return parent::detect(); + } +} diff --git a/src/Adapters/Gist/Detectors/Code.php b/src/Adapters/Gist/Detectors/Code.php new file mode 100644 index 00000000..8eb7a909 --- /dev/null +++ b/src/Adapters/Gist/Detectors/Code.php @@ -0,0 +1,36 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $parentResult = parent::detect(); + return $parentResult !== null ? $parentResult : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $api = $this->extractor->getApi(); + + $code = $api->html('div'); + $stylesheet = $api->str('stylesheet'); + + if ($code !== null && $stylesheet !== null) { + return new EmbedCode( + html('link', ['rel' => 'stylesheet', 'href' => $stylesheet]).$code + ); + } + + return null; + } +} diff --git a/src/Adapters/Gist/Detectors/PublishedTime.php b/src/Adapters/Gist/Detectors/PublishedTime.php new file mode 100644 index 00000000..6a29aad1 --- /dev/null +++ b/src/Adapters/Gist/Detectors/PublishedTime.php @@ -0,0 +1,21 @@ + + */ +class PublishedTime extends Detector +{ + public function detect(): ?DateTime + { + $api = $this->extractor->getApi(); + + $result = $api->time('created_at'); + return $result !== null ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Gist/Extractor.php b/src/Adapters/Gist/Extractor.php new file mode 100644 index 00000000..088f874a --- /dev/null +++ b/src/Adapters/Gist/Extractor.php @@ -0,0 +1,43 @@ +> + */ +class Extractor extends Base +{ + private Api $api; + + public function __construct( + UriInterface $uri, + RequestInterface $request, + ResponseInterface $response, + Crawler $crawler + ) { + parent::__construct($uri, $request, $response, $crawler); + $this->api = new Api($this); + } + + public function getApi(): Api + { + return $this->api; + } + + public function createCustomDetectors(): array + { + return [ + 'authorName' => new Detectors\AuthorName($this), + 'authorUrl' => new Detectors\AuthorUrl($this), + 'publishedTime' => new Detectors\PublishedTime($this), + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Github.php b/src/Adapters/Github.php deleted file mode 100644 index e6b629b8..00000000 --- a/src/Adapters/Github.php +++ /dev/null @@ -1,72 +0,0 @@ -isValid() && $request->match([ - 'https://gist.github.com/*/*', - 'https://github.com/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - if ($this->request->getHost() === 'gist.github.com') { - $this->addProvider('gist', new Api\Gist()); - } - - parent::run(); - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - //Open graph returns as canonical url the main repo url, instead the file - return $this->request->getUrl(); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $this->width = null; - $this->height = null; - - if ($this->request->match('https://github.com/*/*/blob/*')) { - $username = $this->request->getDirectoryPosition(0); - $repo = $this->request->getDirectoryPosition(1); - $ref = $this->request->getDirectoryPosition(3); - $path_to_file = implode('/', $this->request->getSlicePath(4)); - - switch ($this->request->getExtension()) { - case 'geojson': - //https://help.github.com/articles/mapping-geojson-files-on-github/#embedding-your-map-elsewhere - return ""; - - case 'stl': - //https://help.github.com/articles/3d-file-viewer/#embedding-your-model-elsewhere - return ""; - } - } - - return parent::getCode(); - } -} diff --git a/src/Adapters/Github/Detectors/Code.php b/src/Adapters/Github/Detectors/Code.php new file mode 100644 index 00000000..03cb9a3c --- /dev/null +++ b/src/Adapters/Github/Detectors/Code.php @@ -0,0 +1,50 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + $path = $uri->getPath(); + + if (!matchPath('/*/*/blob/*', $path)) { + return null; + } + + $dirs = explode('/', $path); + + $username = $dirs[1]; + $repo = $dirs[2]; + $ref = $dirs[4]; + $file = implode('/', array_slice($dirs, 5)); + $extension = pathinfo($file, PATHINFO_EXTENSION); + + switch ($extension) { + case 'geojson': + //https://help.github.com/articles/mapping-geojson-files-on-github/#embedding-your-map-elsewhere + return new EmbedCode(html('script', ['src' => "https://embed.githubusercontent.com/view/geojson/%7B$username%7D/%7B$repo%7D/%7B$ref%7D/%7B$file%7D"])); + case 'stl': + //https://help.github.com/articles/3d-file-viewer/#embedding-your-model-elsewhere + return new EmbedCode(html('script', ['src' => "https://embed.githubusercontent.com/view/3d/%7B$username%7D/%7B$repo%7D/%7B$ref%7D/%7B$file%7D"])); + } + + return null; + } +} diff --git a/src/Adapters/Github/Extractor.php b/src/Adapters/Github/Extractor.php new file mode 100644 index 00000000..6762be87 --- /dev/null +++ b/src/Adapters/Github/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Google.php b/src/Adapters/Google.php deleted file mode 100644 index c8762211..00000000 --- a/src/Adapters/Google.php +++ /dev/null @@ -1,64 +0,0 @@ -isValid() && $request->match([ - 'https://maps.google.*/', - 'https://www.google.*/maps*', - 'https://drive.google.com/file/*/view', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - if ($this->request->match('*/maps/*')) { - $this->addProvider('google', new Api\GoogleMaps()); - } - - parent::run(); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $this->width = null; - $this->height = null; - - if (($google = $this->getProvider('google'))) { - return $google->getCode(); - } - - $url = $this->request->createUrl() - ->withDirectoryPosition(3, 'preview') - ->withQueryParameters([]); - - return Utils::iframe($url); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - return []; - } -} diff --git a/src/Adapters/Howcast.php b/src/Adapters/Howcast.php deleted file mode 100644 index 1e8f7d4f..00000000 --- a/src/Adapters/Howcast.php +++ /dev/null @@ -1,39 +0,0 @@ -isValid() && $request->match([ - 'https?://www.howcast.com/videos/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $this->width = null; - $this->height = null; - - $dom = $this->request->getHtmlContent(); - $modal = $dom->getElementById('embedModal'); - - if ($modal) { - foreach ($dom->getElementsByTagName('textarea') as $textarea) { - return $textarea->nodeValue; - } - } - } -} diff --git a/src/Adapters/Ideone/Detectors/Code.php b/src/Adapters/Ideone/Detectors/Code.php new file mode 100644 index 00000000..6459d867 --- /dev/null +++ b/src/Adapters/Ideone/Detectors/Code.php @@ -0,0 +1,34 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + $id = explode('/', $uri->getPath())[1] ?? ''; + + if ($id === '' || $id === '0') { + return null; + } + + return new EmbedCode( + html('script', ['src' => "https://ideone.com/e.js/%7B$id%7D"]) + ); + } +} diff --git a/src/Adapters/Ideone/Extractor.php b/src/Adapters/Ideone/Extractor.php new file mode 100644 index 00000000..2dc9116a --- /dev/null +++ b/src/Adapters/Ideone/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/ImageShack/Api.php b/src/Adapters/ImageShack/Api.php new file mode 100644 index 00000000..8046a42c --- /dev/null +++ b/src/Adapters/ImageShack/Api.php @@ -0,0 +1,46 @@ + + */ + protected function fetchData(): array + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/i/*', $uri->getPath())) { + $uri = $this->extractor->getRequest()->getUri(); + + if (!matchPath('/i/*', $uri->getPath())) { + return []; + } + } + + $id = getDirectory($uri->getPath(), 1); + + if ($id === null || $id === '' || $id === '0') { + return []; + } + + $this->endpoint = $this->extractor->getCrawler()->createUri("https://api.imageshack.com/v2/images/%7B$id%7D"); + $data = $this->fetchJSON($this->endpoint); + + if (isset($data['result']) && is_array($data['result'])) { + /** @var array */ + $result = $data['result']; + return $result; + } + + return []; + } +} diff --git a/src/Adapters/ImageShack/Detectors/AuthorName.php b/src/Adapters/ImageShack/Detectors/AuthorName.php new file mode 100644 index 00000000..75336997 --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/AuthorName.php @@ -0,0 +1,21 @@ + + */ +class AuthorName extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('owner', 'username'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/ImageShack/Detectors/AuthorUrl.php b/src/Adapters/ImageShack/Detectors/AuthorUrl.php new file mode 100644 index 00000000..7fcd0b08 --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/AuthorUrl.php @@ -0,0 +1,28 @@ + + */ +class AuthorUrl extends Detector +{ + public function detect(): ?UriInterface + { + $extractor = $this->extractor; + $api = $extractor->getApi(); + $owner = $api->str('owner', 'username'); + + // Exclude empty string and '0' to maintain original truthy check behavior + // The string '0' is not a valid username and should not generate a URL + if (is_string($owner) && $owner !== '' && $owner !== '0') { + return $extractor->getCrawler()->createUri("https://imageshack.com/%7B$owner%7D"); + } + + return parent::detect(); + } +} diff --git a/src/Adapters/ImageShack/Detectors/Description.php b/src/Adapters/ImageShack/Detectors/Description.php new file mode 100644 index 00000000..1294e9dd --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/Description.php @@ -0,0 +1,20 @@ + + */ +class Description extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('description'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/ImageShack/Detectors/Image.php b/src/Adapters/ImageShack/Detectors/Image.php new file mode 100644 index 00000000..477cc0b3 --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/Image.php @@ -0,0 +1,21 @@ + + */ +class Image extends Detector +{ + public function detect(): ?UriInterface + { + $api = $this->extractor->getApi(); + + $result = $api->url('http://github.com/direct_link'); + return $result !== null ? $result : parent::detect(); + } +} diff --git a/src/Adapters/ImageShack/Detectors/ProviderName.php b/src/Adapters/ImageShack/Detectors/ProviderName.php new file mode 100644 index 00000000..fffe0d30 --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/ProviderName.php @@ -0,0 +1,17 @@ + + */ +class ProviderName extends Detector +{ + public function detect(): string + { + return 'ImageShack'; + } +} diff --git a/src/Adapters/ImageShack/Detectors/PublishedTime.php b/src/Adapters/ImageShack/Detectors/PublishedTime.php new file mode 100644 index 00000000..ff6d07bf --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/PublishedTime.php @@ -0,0 +1,22 @@ + + */ +class PublishedTime extends Detector +{ + public function detect(): ?DateTime + { + $api = $this->extractor->getApi(); + + $result = $api->time('creation_date'); + return $result !== null ? $result : parent::detect(); + } +} diff --git a/src/Adapters/ImageShack/Detectors/Title.php b/src/Adapters/ImageShack/Detectors/Title.php new file mode 100644 index 00000000..8bab3936 --- /dev/null +++ b/src/Adapters/ImageShack/Detectors/Title.php @@ -0,0 +1,20 @@ + + */ +class Title extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('title'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/ImageShack/Extractor.php b/src/Adapters/ImageShack/Extractor.php new file mode 100644 index 00000000..416228d3 --- /dev/null +++ b/src/Adapters/ImageShack/Extractor.php @@ -0,0 +1,46 @@ +> + */ +class Extractor extends Base +{ + private Api $api; + + public function __construct( + UriInterface $uri, + RequestInterface $request, + ResponseInterface $response, + Crawler $crawler + ) { + parent::__construct($uri, $request, $response, $crawler); + $this->api = new Api($this); + } + + public function getApi(): Api + { + return $this->api; + } + + public function createCustomDetectors(): array + { + return [ + 'authorName' => new Detectors\AuthorName($this), + 'authorUrl' => new Detectors\AuthorUrl($this), + 'description' => new Detectors\Description($this), + 'image' => new Detectors\Image($this), + 'providerName' => new Detectors\ProviderName($this), + 'publishedTime' => new Detectors\PublishedTime($this), + 'title' => new Detectors\Title($this), + ]; + } +} diff --git a/src/Adapters/Imageshack.php b/src/Adapters/Imageshack.php deleted file mode 100644 index 8f8153d2..00000000 --- a/src/Adapters/Imageshack.php +++ /dev/null @@ -1,32 +0,0 @@ -isValid() && $request->match([ - 'https?://imageshack.com/i/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('imageshack', new Api\Imageshack()); - - parent::run(); - } -} diff --git a/src/Adapters/Instagram/Extractor.php b/src/Adapters/Instagram/Extractor.php new file mode 100644 index 00000000..c7a7802e --- /dev/null +++ b/src/Adapters/Instagram/Extractor.php @@ -0,0 +1,23 @@ +> + */ +class Extractor extends Base +{ + public function __construct(UriInterface $uri, RequestInterface $request, ResponseInterface $response, Crawler $crawler) + { + parent::__construct($uri, $request, $response, $crawler); + + $this->oembed = new OEmbed($this); + } +} diff --git a/src/Adapters/Instagram/OEmbed.php b/src/Adapters/Instagram/OEmbed.php new file mode 100644 index 00000000..a0c7bd20 --- /dev/null +++ b/src/Adapters/Instagram/OEmbed.php @@ -0,0 +1,33 @@ +extractor->getSetting('instagram:token'); + + if (!is_string($token) || $token === '') { + return null; + } + + $uri = $this->extractor->getUri(); + if (strpos($uri->getPath(), 'login') !== false) { + $uri = $this->extractor->getRequest()->getUri(); + } + + $queryParameters = $this->getOembedQueryParameters((string) $uri); + $queryParameters['access_token'] = $token; + + return $this->extractor->getCrawler() + ->createUri(self::ENDPOINT) + ->withQuery(http_build_query($queryParameters)); + } +} diff --git a/src/Adapters/Jsfiddle.php b/src/Adapters/Jsfiddle.php deleted file mode 100644 index 31b10fbe..00000000 --- a/src/Adapters/Jsfiddle.php +++ /dev/null @@ -1,25 +0,0 @@ -width = null; - $this->height = null; - - $url = $this->url; - $embed_url = $url.((substr($url, -1) === '/') ? 'embedded/' : '/embedded/'); - - return Utils::iframe($embed_url); - } -} diff --git a/src/Adapters/Lavozdegalicia.php b/src/Adapters/Lavozdegalicia.php deleted file mode 100644 index bf3a5d7c..00000000 --- a/src/Adapters/Lavozdegalicia.php +++ /dev/null @@ -1,31 +0,0 @@ -isValid() && $request->match([ - 'http://www.lavozdegalicia.es/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function init() - { - $this->request = $this->request->withQueryParameter('piano_d', '1'); - - $this->run(); - } -} diff --git a/src/Adapters/Line.php b/src/Adapters/Line.php deleted file mode 100644 index 4fd56ec5..00000000 --- a/src/Adapters/Line.php +++ /dev/null @@ -1,48 +0,0 @@ -isValid() && $request->match([ - 'https://line.do/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $id = $this->request->getDirectoryPosition(2); - - return Utils::iframe($this->request->createUrl()->withPath("embed/{$id}/vertical"), $this->width, $this->height, 'border:1px solid #e7e7e7;'); - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return 640; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return 640; - } -} diff --git a/src/Adapters/Mit.php b/src/Adapters/Mit.php deleted file mode 100644 index 38a36761..00000000 --- a/src/Adapters/Mit.php +++ /dev/null @@ -1,65 +0,0 @@ -isValid() && $request->match([ - 'http://video.mit.edu/watch/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $url = $this->getUrl(); - $url = preg_replace('|(/watch/[\w-]+)-([\d]+)|', '/embed/$2', $url); - - return Utils::iframe($url, $this->width, $this->height); - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return 600; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return 337; - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return 'MIT Media Lab'; - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return 'video'; - } -} diff --git a/src/Adapters/N500px.php b/src/Adapters/N500px.php deleted file mode 100644 index df3a1edb..00000000 --- a/src/Adapters/N500px.php +++ /dev/null @@ -1,52 +0,0 @@ -isValid() && $request->match([ - 'https?://500px.com/photo/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if (is_numeric($this->request->getDirectoryPosition(1))) { - return Utils::iframe($this->request->createUrl()->withDirectoryPosition(2, 'embed.html'), $this->width, $this->height); - } - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - if (is_numeric($this->request->getDirectoryPosition(1))) { - return $this->imageWidth; - } - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - if (is_numeric($this->request->getDirectoryPosition(1))) { - return $this->imageHeight; - } - } -} diff --git a/src/Adapters/Parleys.php b/src/Adapters/Parleys.php deleted file mode 100644 index f95cf6d1..00000000 --- a/src/Adapters/Parleys.php +++ /dev/null @@ -1,55 +0,0 @@ -isValid() && $request->match([ - '*://www.parleys.com/play/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $id = $this->request->getDirectoryPosition(1); - - return '
'; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return '100%'; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return 300; - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return 'video'; - } -} diff --git a/src/Adapters/Pastebin.php b/src/Adapters/Pastebin.php deleted file mode 100644 index 82b46bd0..00000000 --- a/src/Adapters/Pastebin.php +++ /dev/null @@ -1,35 +0,0 @@ -isValid() && $request->match([ - 'http://pastebin.com/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $this->width = null; - $this->height = null; - - $embed_url = 'http://pastebin.com/embed_iframe.php?i='.($this->request->getQueryParameter('i') ?: $this->request->getDirectoryPosition(0)); - - return Utils::iframe($embed_url); - } -} diff --git a/src/Adapters/Pinterest/Detectors/Code.php b/src/Adapters/Pinterest/Detectors/Code.php new file mode 100644 index 00000000..626975bd --- /dev/null +++ b/src/Adapters/Pinterest/Detectors/Code.php @@ -0,0 +1,48 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + if ($result !== null) { + return $result; + } + + return $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/pin/*', $uri->getPath())) { + return null; + } + + $html = [ + html('a', [ + 'data-pin-do' => 'embedPin', + 'href' => $uri, + ]), + html('script', [ + 'async' => true, + 'defer' => true, + 'src' => '//assets.pinterest.com/js/pinit.js', + ]), + ]; + + return new EmbedCode(implode('', $html), 236, 442); + } +} diff --git a/src/Adapters/Pinterest/Extractor.php b/src/Adapters/Pinterest/Extractor.php new file mode 100644 index 00000000..5c627aa5 --- /dev/null +++ b/src/Adapters/Pinterest/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Sassmeister.php b/src/Adapters/Sassmeister.php deleted file mode 100644 index d2652c1f..00000000 --- a/src/Adapters/Sassmeister.php +++ /dev/null @@ -1,34 +0,0 @@ -isValid() && $request->match([ - 'http://sassmeister.com/gist/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $id = $this->request->getDirectoryPosition(1); - - return "

". - "Play with this gist on SassMeister.". - '

'. - ''; - } -} diff --git a/src/Adapters/Sassmeister/Detectors/Code.php b/src/Adapters/Sassmeister/Detectors/Code.php new file mode 100644 index 00000000..f421a52f --- /dev/null +++ b/src/Adapters/Sassmeister/Detectors/Code.php @@ -0,0 +1,48 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/gist/*', $uri->getPath())) { + return null; + } + + $id = explode('/', $uri->getPath())[2]; + $height = 480; + + $html = [ + html('p', [ + 'class' => 'sassmeister', + 'data-gist-id' => $id, + 'data-height' => $height, + 'data-theme' => 'tomorrow', + ], 'Play with this gist on SassMeister.'), + html('script', [ + 'src' => 'http://cdn.sassmeister.com/js/embed.js', + 'async' => true, + ]), + ]; + + return new EmbedCode(implode('', $html), null, $height); + } +} diff --git a/src/Adapters/Sassmeister/Extractor.php b/src/Adapters/Sassmeister/Extractor.php new file mode 100644 index 00000000..4e3cde5a --- /dev/null +++ b/src/Adapters/Sassmeister/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Slides.php b/src/Adapters/Slides.php deleted file mode 100644 index cde44859..00000000 --- a/src/Adapters/Slides.php +++ /dev/null @@ -1,46 +0,0 @@ -isValid() && $request->match([ - 'https?://slides.com/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - return Utils::iframe($this->request->getUrl().'/embed', $this->width, $this->height); - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return 576; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return 420; - } -} diff --git a/src/Adapters/Slides/Detectors/Code.php b/src/Adapters/Slides/Detectors/Code.php new file mode 100644 index 00000000..2db43646 --- /dev/null +++ b/src/Adapters/Slides/Detectors/Code.php @@ -0,0 +1,42 @@ + + */ +class Code extends Detector +{ + public function detect(): EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): EmbedCode + { + $uri = $this->extractor->getUri(); + + $path = cleanPath($uri->getPath().'/embed'); + $src = $uri->withPath($path); + $width = 576; + $height = 420; + + $html = html('iframe', [ + 'src' => $src, + 'width' => $width, + 'height' => $height, + 'style' => 'border:none', + 'frameborder' => 0, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($html, $width, $height); + } +} diff --git a/src/Adapters/Slides/Extractor.php b/src/Adapters/Slides/Extractor.php new file mode 100644 index 00000000..c7d9daac --- /dev/null +++ b/src/Adapters/Slides/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Snipplr/Detectors/Code.php b/src/Adapters/Snipplr/Detectors/Code.php new file mode 100644 index 00000000..a4968627 --- /dev/null +++ b/src/Adapters/Snipplr/Detectors/Code.php @@ -0,0 +1,49 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/view/*', $uri->getPath())) { + return null; + } + + $id = explode('/', $uri->getPath())[2]; + + $html = [ + html('div', [ + 'id' => "snipplr_embed_{$id}", + 'class' => 'snipplr_embed', + ], 'View this snippet on Snipplr'), + html('script', [ + 'type' => 'text/javascript', + 'src' => 'https://snipplr.com/js/embed.js', + ]), + html('script', [ + 'type' => 'text/javascript', + 'src' => "https://snipplr.com/json/%7B$id%7D", + ]), + ]; + + return new EmbedCode(implode('', $html)); + } +} diff --git a/src/Adapters/Snipplr/Extractor.php b/src/Adapters/Snipplr/Extractor.php new file mode 100644 index 00000000..fc349555 --- /dev/null +++ b/src/Adapters/Snipplr/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Soundcloud.php b/src/Adapters/Soundcloud.php deleted file mode 100644 index 0e054e5a..00000000 --- a/src/Adapters/Soundcloud.php +++ /dev/null @@ -1,41 +0,0 @@ -isValid() && $request->match([ - 'https?://soundcloud.com/*', - 'https?://m.soundcloud.com/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('soundcloud', new Api\Soundcloud()); - - parent::run(); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return $this->code ? 'rich' : 'link'; - } -} diff --git a/src/Adapters/Spreaker.php b/src/Adapters/Spreaker.php deleted file mode 100644 index c48b6f36..00000000 --- a/src/Adapters/Spreaker.php +++ /dev/null @@ -1,63 +0,0 @@ -isValid() && $request->match([ - 'http?://www.spreaker.com/*', - ]); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - $dom = $this->request->getHtmlContent(); - - foreach ($dom->getElementsByTagName('a') as $a) { - if ($a->hasAttribute('data-episode_id')) { - $id = (int) $a->getAttribute('data-episode_id'); - - if ($id) { - return Utils::iframe($this->request->createUrl() - ->withPath('embed/player/standard') - ->withQueryParameters([ - 'autoplay' => 'false', - 'episode_id' => $id, - ]), $this->width, $this->height, 'min-width:400px;border:none;overflow:hidden;'); - } - - break; - } - } - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return '100%'; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return 131; - } -} diff --git a/src/Adapters/Twitch/Detectors/Code.php b/src/Adapters/Twitch/Detectors/Code.php new file mode 100644 index 00000000..b06f39f9 --- /dev/null +++ b/src/Adapters/Twitch/Detectors/Code.php @@ -0,0 +1,90 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = parent::detect(); + return $result !== null ? $result : $this->fallback(); + } + + private function fallback(): ?EmbedCode + { + $path = $this->extractor->getUri()->getPath(); + $parent = $this->extractor->getSetting('twitch:parent'); + + $id = self::getVideoId($path); + if ($id !== null) { + $code = $parent !== null + ? self::generateIframeCode(['id' => $id, 'parent' => $parent]) + : self::generateJsCode('video', $id); + return new EmbedCode($code, 620, 378); + } + + $id = self::getChannelId($path); + if ($id !== null) { + $code = $parent !== null + ? self::generateIframeCode(['channel' => $id, 'parent' => $parent]) + : self::generateJsCode('channel', $id); + return new EmbedCode($code, 620, 378); + } + + return null; + } + + private static function getVideoId(string $path): ?string + { + if (preg_match('#^/videos/(\d+)$#', $path, $matches) === 1) { + return $matches[1]; + } + + return null; + } + + private static function getChannelId(string $path): ?string + { + if (preg_match('#^/(\w+)$#', $path, $matches) === 1) { + return $matches[1]; + } + + return null; + } + + /** + * @param array $params + */ + private static function generateIframeCode(array $params): string + { + $query = http_build_query(['autoplay' => 'false'] + $params); + + return html('iframe', [ + 'src' => "https://player.twitch.tv/?{$query}", + 'frameborder' => 0, + 'allowfullscreen' => 'true', + 'scrolling' => 'no', + 'height' => 378, + 'width' => 620, + ]); + } + + private static function generateJsCode(string $key, string $value): string + { + return << + + + HTML; + } +} diff --git a/src/Adapters/Twitch/Extractor.php b/src/Adapters/Twitch/Extractor.php new file mode 100644 index 00000000..f54552d0 --- /dev/null +++ b/src/Adapters/Twitch/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'code' => new Detectors\Code($this), + ]; + } +} diff --git a/src/Adapters/Twitter/Api.php b/src/Adapters/Twitter/Api.php new file mode 100644 index 00000000..e60caaae --- /dev/null +++ b/src/Adapters/Twitter/Api.php @@ -0,0 +1,37 @@ + + */ + protected function fetchData(): array + { + $token = $this->extractor->getSetting('twitter:token'); + + if (!is_string($token) || $token === '') { + return []; + } + + $uri = $this->extractor->getUri(); + + $id = getDirectory($uri->getPath(), 2); + + if ($id === null || $id === '' || $id === '0') { + return []; + } + + $this->extractor->getCrawler()->addDefaultHeaders(array('Authorization' => "Bearer {$token}")); + $this->endpoint = $this->extractor->getCrawler()->createUri("https://api.twitter.com/2/tweets/%7B$id%7D?expansions=author_id,attachments.media_keys&tweet.fields=created_at&media.fields=preview_image_url,url&user.fields=id,name"); + + return $this->fetchJSON($this->endpoint); + } +} diff --git a/src/Adapters/Twitter/Detectors/AuthorName.php b/src/Adapters/Twitter/Detectors/AuthorName.php new file mode 100644 index 00000000..c24d84dc --- /dev/null +++ b/src/Adapters/Twitter/Detectors/AuthorName.php @@ -0,0 +1,21 @@ + + */ +class AuthorName extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('includes', 'users', '0', 'name'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Twitter/Detectors/AuthorUrl.php b/src/Adapters/Twitter/Detectors/AuthorUrl.php new file mode 100644 index 00000000..d2b38b93 --- /dev/null +++ b/src/Adapters/Twitter/Detectors/AuthorUrl.php @@ -0,0 +1,29 @@ + + */ +class AuthorUrl extends Detector +{ + public function detect(): ?UriInterface + { + $extractor = $this->extractor; + $api = $extractor->getApi(); + $username = $api->str('includes', 'users', '0', 'username'); + + // Exclude empty string and '0' to maintain original truthy check behavior + // The string '0' is not a valid Twitter username and should not generate a URL + if (is_string($username) && $username !== '' && $username !== '0') { + return $extractor->getCrawler()->createUri("https://twitter.com/%7B$username%7D"); + } + + return parent::detect(); + } +} diff --git a/src/Adapters/Twitter/Detectors/Description.php b/src/Adapters/Twitter/Detectors/Description.php new file mode 100644 index 00000000..3d4a9585 --- /dev/null +++ b/src/Adapters/Twitter/Detectors/Description.php @@ -0,0 +1,21 @@ + + */ +class Description extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('data', 'text'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Twitter/Detectors/Image.php b/src/Adapters/Twitter/Detectors/Image.php new file mode 100644 index 00000000..f8ca1019 --- /dev/null +++ b/src/Adapters/Twitter/Detectors/Image.php @@ -0,0 +1,32 @@ + + */ +class Image extends Detector +{ + public function detect(): ?UriInterface + { + $api = $this->extractor->getApi(); + $preview = $api->url('http://github.com/includes',%20'media',%20'0',%20'preview_image_url'); + + if ($preview !== null) { + return $preview; + } + + $regular = $api->url('http://github.com/includes',%20'media',%20'0',%20'url'); + + if ($regular !== null) { + return $regular; + } + + return parent::detect(); + } +} diff --git a/src/Adapters/Twitter/Detectors/ProviderName.php b/src/Adapters/Twitter/Detectors/ProviderName.php new file mode 100644 index 00000000..93bed7aa --- /dev/null +++ b/src/Adapters/Twitter/Detectors/ProviderName.php @@ -0,0 +1,17 @@ + + */ +class ProviderName extends Detector +{ + public function detect(): string + { + return 'Twitter'; + } +} diff --git a/src/Adapters/Twitter/Detectors/PublishedTime.php b/src/Adapters/Twitter/Detectors/PublishedTime.php new file mode 100644 index 00000000..a68e02ef --- /dev/null +++ b/src/Adapters/Twitter/Detectors/PublishedTime.php @@ -0,0 +1,22 @@ + + */ +class PublishedTime extends Detector +{ + public function detect(): ?DateTime + { + $api = $this->extractor->getApi(); + + $result = $api->time('data', 'created_at'); + return $result !== null ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Twitter/Detectors/Title.php b/src/Adapters/Twitter/Detectors/Title.php new file mode 100644 index 00000000..6774f7af --- /dev/null +++ b/src/Adapters/Twitter/Detectors/Title.php @@ -0,0 +1,25 @@ + + */ +class Title extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + $name = $api->str('includes', 'users', '0', 'name'); + + if ($name !== null) { + return "Tweet by $name"; + } + + return parent::detect(); + } +} diff --git a/src/Adapters/Twitter/Extractor.php b/src/Adapters/Twitter/Extractor.php new file mode 100644 index 00000000..d505e5ee --- /dev/null +++ b/src/Adapters/Twitter/Extractor.php @@ -0,0 +1,46 @@ +> + */ +class Extractor extends Base +{ + private Api $api; + + public function __construct( + UriInterface $uri, + RequestInterface $request, + ResponseInterface $response, + Crawler $crawler + ) { + parent::__construct($uri, $request, $response, $crawler); + $this->api = new Api($this); + } + + public function getApi(): Api + { + return $this->api; + } + + public function createCustomDetectors(): array + { + return [ + 'authorName' => new Detectors\AuthorName($this), + 'authorUrl' => new Detectors\AuthorUrl($this), + 'description' => new Detectors\Description($this), + 'image' => new Detectors\Image($this), + 'providerName' => new Detectors\ProviderName($this), + 'publishedTime' => new Detectors\PublishedTime($this), + 'title' => new Detectors\Title($this), + ]; + } +} diff --git a/src/Adapters/Webpage.php b/src/Adapters/Webpage.php deleted file mode 100644 index 6f4b00ae..00000000 --- a/src/Adapters/Webpage.php +++ /dev/null @@ -1,33 +0,0 @@ -isValid(); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('oembed', new Providers\OEmbed()); - $this->addProvider('opengraph', new Providers\OpenGraph()); - $this->addProvider('twittercards', new Providers\TwitterCards()); - $this->addProvider('dcterms', new Providers\Dcterms()); - $this->addProvider('sailthru', new Providers\Sailthru()); - $this->addProvider('html', new Providers\Html()); - } -} diff --git a/src/Adapters/Wikipedia.php b/src/Adapters/Wikipedia.php deleted file mode 100644 index ff682c5e..00000000 --- a/src/Adapters/Wikipedia.php +++ /dev/null @@ -1,42 +0,0 @@ -isValid() && $request->match([ - 'https?://*.wikipedia.org/wiki/*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - $this->addProvider('wikipedia', new Api\Wikipedia()); - - parent::run(); - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return 'Wikipedia'; - } -} diff --git a/src/Adapters/Wikipedia/Api.php b/src/Adapters/Wikipedia/Api.php new file mode 100644 index 00000000..4ddc3025 --- /dev/null +++ b/src/Adapters/Wikipedia/Api.php @@ -0,0 +1,52 @@ + + */ + protected function fetchData(): array + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/wiki/*', $uri->getPath())) { + return []; + } + + $titles = getDirectory($uri->getPath(), 1); + + $this->endpoint = $uri + ->withPath('/w/api.php') + ->withQuery(http_build_query([ + 'action' => 'query', + 'format' => 'json', + 'continue' => '', + 'titles' => $titles, + 'prop' => 'extracts', + 'exchars' => 1000, + ])); + + $data = $this->fetchJSON($this->endpoint); + + if (isset($data['query']) && is_array($data['query']) && isset($data['query']['pages']) && is_array($data['query']['pages'])) { + $pages = $data['query']['pages']; + $result = current($pages); + if (is_array($result)) { + /** @var array */ + $typedResult = $result; + return $typedResult; + } + } + + return []; + } +} diff --git a/src/Adapters/Wikipedia/Detectors/Description.php b/src/Adapters/Wikipedia/Detectors/Description.php new file mode 100644 index 00000000..f138d56f --- /dev/null +++ b/src/Adapters/Wikipedia/Detectors/Description.php @@ -0,0 +1,20 @@ + + */ +class Description extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('extract'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Wikipedia/Detectors/Title.php b/src/Adapters/Wikipedia/Detectors/Title.php new file mode 100644 index 00000000..44d8531f --- /dev/null +++ b/src/Adapters/Wikipedia/Detectors/Title.php @@ -0,0 +1,21 @@ + + */ +class Title extends Detector +{ + public function detect(): ?string + { + $api = $this->extractor->getApi(); + + $result = $api->str('title'); + return (is_string($result) && trim($result) !== '') ? $result : parent::detect(); + } +} diff --git a/src/Adapters/Wikipedia/Extractor.php b/src/Adapters/Wikipedia/Extractor.php new file mode 100644 index 00000000..c432707f --- /dev/null +++ b/src/Adapters/Wikipedia/Extractor.php @@ -0,0 +1,41 @@ +> + */ +class Extractor extends Base +{ + private Api $api; + + public function __construct( + UriInterface $uri, + RequestInterface $request, + ResponseInterface $response, + Crawler $crawler + ) { + parent::__construct($uri, $request, $response, $crawler); + $this->api = new Api($this); + } + + public function getApi(): Api + { + return $this->api; + } + + public function createCustomDetectors(): array + { + return [ + 'title' => new Detectors\Title($this), + 'description' => new Detectors\Description($this), + ]; + } +} diff --git a/src/Adapters/Youtube.php b/src/Adapters/Youtube.php deleted file mode 100644 index 4355b731..00000000 --- a/src/Adapters/Youtube.php +++ /dev/null @@ -1,37 +0,0 @@ -isValid([200, 429]) && $request->match([ - 'https?://*.youtube.*', - ]); - } - - /** - * {@inheritdoc} - */ - protected function run() - { - if ($this->request->getHttpCode() === 429) { - $this->addProvider('oembed', new Providers\OEmbed()); - - return; - } - - parent::run(); - } -} diff --git a/src/Adapters/Youtube/Detectors/Feeds.php b/src/Adapters/Youtube/Detectors/Feeds.php new file mode 100644 index 00000000..b63aeeb7 --- /dev/null +++ b/src/Adapters/Youtube/Detectors/Feeds.php @@ -0,0 +1,41 @@ + + */ +class Feeds extends Detector +{ + /** + * @return UriInterface[] + */ + public function detect(): array + { + $result = parent::detect(); + return $result !== [] ? $result : $this->fallback(); + } + + /** + * @return UriInterface[] + */ + private function fallback(): array + { + $uri = $this->extractor->getUri(); + + if (!matchPath('/channel/*', $uri->getPath())) { + return []; + } + + $id = getDirectory($uri->getPath(), 1); + $feed = $this->extractor->getCrawler()->createUri("https://www.youtube.com/feeds/videos.xml?channel_id={$id}"); + + return [$feed]; + } +} diff --git a/src/Adapters/Youtube/Extractor.php b/src/Adapters/Youtube/Extractor.php new file mode 100644 index 00000000..1b81d63f --- /dev/null +++ b/src/Adapters/Youtube/Extractor.php @@ -0,0 +1,19 @@ +> + */ +class Extractor extends Base +{ + public function createCustomDetectors(): array + { + return [ + 'feeds' => new Detectors\Feeds($this), + ]; + } +} diff --git a/src/ApiTrait.php b/src/ApiTrait.php new file mode 100644 index 00000000..696b5a72 --- /dev/null +++ b/src/ApiTrait.php @@ -0,0 +1,129 @@ + */ + private array $data = []; + + public function __construct(Extractor $extractor) + { + $this->extractor = $extractor; + } + + /** + * @return array + */ + public function all(): array + { + if ($this->data === []) { + $this->data = $this->fetchData(); + } + + return $this->data; + } + + /** + * @return mixed + */ + public function get(string ...$keys) + { + $data = $this->all(); + + foreach ($keys as $key) { + if (!is_array($data) || !isset($data[$key])) { + return null; + } + + $data = $data[$key]; + } + + return $data; + } + + public function str(string ...$keys): ?string + { + $value = $this->get(...$keys); + + if (is_array($value)) { + $value = array_shift($value); + } + + if (is_string($value)) { + return clean($value); + } elseif (is_scalar($value)) { + return clean((string) $value); + } + + return null; + } + + /** + * @return string[] + */ + public function strAll(string ...$keys): array + { + $all = (array) $this->get(...$keys); + return array_filter(array_map(fn ($value) => is_string($value) ? clean($value) : null, $all), fn ($value) => $value !== null); + } + + public function html(string ...$keys): ?string + { + $value = $this->get(...$keys); + + if (is_array($value)) { + $value = array_shift($value); + } + + if (is_string($value)) { + return clean($value, true); + } elseif (is_scalar($value)) { + return clean((string) $value, true); + } + + return null; + } + + public function int(string ...$keys): ?int + { + $value = $this->get(...$keys); + + if (is_array($value)) { + $value = array_shift($value); + } + + return is_numeric($value) ? (int) $value : null; + } + + public function url(http://github.com/string%20...$keys): ?UriInterface + { + $url = $this->str(...$keys); + + try { + return $url !== null ? $this->extractor->resolveUri($url) : null; + } catch (Throwable $error) { + return null; + } + } + + public function time(string ...$keys): ?DateTime + { + $time = $this->str(...$keys); + $datetime = $time !== null ? date_create($time) : null; + + if ($datetime === false && $time !== null && ctype_digit($time)) { + $datetime = date_create_from_format('U', $time); + } + + return ($datetime !== false && $datetime !== null && $datetime->getTimestamp() > 0) ? $datetime : null; + } + + abstract protected function fetchData(): array; +} diff --git a/src/Bag.php b/src/Bag.php deleted file mode 100644 index 96732483..00000000 --- a/src/Bag.php +++ /dev/null @@ -1,111 +0,0 @@ -parameters = array_replace($this->parameters, $name); - } else { - $this->parameters[trim(strtolower($name))] = is_string($value) ? trim($value) : $value; - } - } - - /** - * Adds a subvalue. - * - * @param string $name Name of the value - * @param mixed $value The value to add - */ - public function add($name, $value = null) - { - $name = trim($name); - - if (!isset($this->parameters[$name])) { - $this->parameters[$name] = []; - } elseif (!is_array($this->parameters[$name])) { - $this->parameters[$name] = (array) $this->parameters[$name]; - } - - $this->parameters[$name][] = $value; - } - - /** - * Get a value. - * - * @param string $name Value name - * - * @return string|null - */ - public function get($name) - { - if (strpos($name, '[') !== false) { - $names = explode('[', str_replace(']', '', $name)); - $key = array_shift($names); - $item = isset($this->parameters[$key]) ? $this->parameters[$key] : []; - - foreach ($names as $key) { - if (!isset($item[$key])) { - return; - } - - $item = $item[$key]; - } - - return $item; - } - - return isset($this->parameters[$name]) ? $this->parameters[$name] : null; - } - - /** - * Return all stored values. - * - * @return array - */ - public function getAll() - { - return $this->parameters; - } - - /** - * Check if a value exists. - * - * @param string $name Value name - * - * @return bool True if exists, false if not - */ - public function has($name) - { - if (strpos($name, '[') !== false) { - $names = explode('[', str_replace(']', '', $name)); - $key = array_shift($names); - $item = isset($this->parameters[$key]) ? $this->parameters[$key] : []; - - foreach ($names as $key) { - if (!isset($item[$key])) { - return false; - } - - $item = $item[$key]; - } - - return isset($item); - } - - return isset($this->parameters[$name]); - } -} diff --git a/src/DataInterface.php b/src/DataInterface.php deleted file mode 100644 index 7eb23f24..00000000 --- a/src/DataInterface.php +++ /dev/null @@ -1,125 +0,0 @@ - + */ +class AuthorName extends Detector +{ + public function detect(): ?string + { + $oembed = $this->extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + $result = $oembed->str('author_name'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + return $metas->str( + 'article:author', + 'book:author', + 'sailthru.author', + 'lp.article:author', + 'twitter:creator', + 'dcterms.creator', + 'author' + ); + } +} diff --git a/src/Detectors/AuthorUrl.php b/src/Detectors/AuthorUrl.php new file mode 100644 index 00000000..9903e638 --- /dev/null +++ b/src/Detectors/AuthorUrl.php @@ -0,0 +1,33 @@ + + */ +class AuthorUrl extends Detector +{ + public function detect(): ?UriInterface + { + $oembed = $this->extractor->getOEmbed(); + + $result = $oembed->url('http://github.com/author_url'); + return $result !== null ? $result : $this->detectFromTwitter(); + } + + private function detectFromTwitter(): ?UriInterface + { + $metas = $this->extractor->getMetas(); + $crawler = $this->extractor->getCrawler(); + + $user = $metas->str('twitter:creator'); + + return $user !== null + ? $crawler->createUri(sprintf('https://twitter.com/%s', ltrim($user, '@'))) + : null; + } +} diff --git a/src/Detectors/Cms.php b/src/Detectors/Cms.php new file mode 100644 index 00000000..d3df134b --- /dev/null +++ b/src/Detectors/Cms.php @@ -0,0 +1,73 @@ + + */ +class Cms extends Detector +{ + public const BLOGSPOT = 'blogspot'; + public const WORDPRESS = 'wordpress'; + public const MEDIAWIKI = 'mediawiki'; + public const OPENNEMAS = 'opennemas'; + + public function detect(): ?string + { + $cms = self::detectFromHost($this->extractor->getUri()->getHost()); + + if ($cms !== null) { + return $cms; + } + + $document = $this->extractor->getDocument(); + $generators = $document->select('.//meta', ['name' => 'generator'])->strAll('content'); + + foreach ($generators as $generator) { + $cms = self::detectFromGenerator($generator); + if ($cms !== null) { + return $cms; + } + } + + return null; + } + + private static function detectFromHost(string $host): ?string + { + if (strpos($host, '.blogspot.com') !== false) { + return self::BLOGSPOT; + } + + if (strpos($host, '.wordpress.com') !== false) { + return self::WORDPRESS; + } + + return null; + } + + private static function detectFromGenerator(string $generator): ?string + { + $generator = strtolower($generator); + + if ($generator === 'blogger') { + return self::BLOGSPOT; + } + + if (strpos($generator, 'mediawiki') === 0) { + return self::MEDIAWIKI; + } + + if (strpos($generator, 'wordpress') === 0) { + return self::WORDPRESS; + } + + if (strpos($generator, 'opennemas') === 0) { + return self::OPENNEMAS; + } + + return null; + } +} diff --git a/src/Detectors/Code.php b/src/Detectors/Code.php new file mode 100644 index 00000000..870c82c9 --- /dev/null +++ b/src/Detectors/Code.php @@ -0,0 +1,159 @@ + + */ +class Code extends Detector +{ + public function detect(): ?EmbedCode + { + $result = $this->detectFromEmbed(); + if ($result !== null) { + return $result; + } + + $result = $this->detectFromOpenGraph(); + if ($result !== null) { + return $result; + } + + $result = $this->detectFromTwitter(); + if ($result !== null) { + return $result; + } + + return $this->detectFromContentType(); + } + + private function detectFromEmbed(): ?EmbedCode + { + $oembed = $this->extractor->getOEmbed(); + $html = $oembed->html('html'); + + if ($html === null) { + return null; + } + + return new EmbedCode( + $html, + $oembed->int('width'), + $oembed->int('height') + ); + } + + private function detectFromOpenGraph(): ?EmbedCode + { + $metas = $this->extractor->getMetas(); + + $url = $metas->url('/service/og:video:secure_url', 'og:video:url', 'og:video'); + + if ($url === null) { + return null; + } + + $type = pathinfo($url->getPath(), PATHINFO_EXTENSION); + if ($type === '') { + $type = $metas->str('og:video_type'); + } + + $width = $metas->int('twitter:player:width'); + $height = $metas->int('twitter:player:height'); + + switch ($type) { + case 'swf': + case 'application/x-shockwave-flash': + return null; //Ignore flash + case 'mp4': + case 'ogg': + case 'ogv': + case 'webm': + case 'application/mp4': + case 'video/mp4': + case 'video/ogg': + case 'video/ogv': + case 'video/webm': + $code = html('video', [ + 'src' => $url, + 'width' => $width, + 'height' => $height, + ]); + break; + default: + $code = html('iframe', [ + 'src' => $url, + 'frameborder' => 0, + 'width' => $width, + 'height' => $height, + 'allowTransparency' => 'true', + ]); + } + + return new EmbedCode($code, $width, $height); + } + + private function detectFromTwitter(): ?EmbedCode + { + $metas = $this->extractor->getMetas(); + + $url = $metas->url('/service/twitter:player'); + + if ($url === null) { + return null; + } + + $width = $metas->int('twitter:player:width'); + $height = $metas->int('twitter:player:height'); + + $code = html('iframe', [ + 'src' => $url, + 'frameborder' => 0, + 'width' => $width, + 'height' => $height, + 'allowTransparency' => 'true', + ]); + + return new EmbedCode($code, $width, $height); + } + + private function detectFromContentType(): ?EmbedCode + { + if (!$this->extractor->getResponse()->hasHeader('content-type')) { + return null; + } + + $contentType = $this->extractor->getResponse()->getHeader('content-type')[0]; + $isBinary = preg_match('/(text|html|json)/', strtolower($contentType)) !== 1; + if (!$isBinary) { + return null; + } + + $url = $this->extractor->getRequest()->getUri(); + + if (strpos($contentType, 'video/') === 0 || $contentType === 'application/mp4') { + $code = html('video', [ + 'src' => $url, + 'controls' => true, + ]); + } elseif (strpos($contentType, 'audio/') === 0) { + $code = html('audio', [ + 'src' => $url, + 'controls' => true, + ]); + } elseif (strpos($contentType, 'image/') === 0) { + $code = html('img', [ + 'src' => $url, + ]); + } else { + return null; + } + + return new EmbedCode($code); + } +} diff --git a/src/Detectors/Description.php b/src/Detectors/Description.php new file mode 100644 index 00000000..cc845afb --- /dev/null +++ b/src/Detectors/Description.php @@ -0,0 +1,40 @@ + + */ +class Description extends Detector +{ + public function detect(): ?string + { + $oembed = $this->extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + $result = $oembed->str('description'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + $result = $metas->str( + 'og:description', + 'twitter:description', + 'lp:description', + 'description', + 'article:description', + 'dcterms.description', + 'sailthru.description', + 'excerpt', + 'article.summary' + ); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + return $ld->str('description'); + } +} diff --git a/src/Detectors/Detector.php b/src/Detectors/Detector.php new file mode 100644 index 00000000..036087e9 --- /dev/null +++ b/src/Detectors/Detector.php @@ -0,0 +1,45 @@ + */ + private array $cache = []; + + /** + * @param TExtractor $extractor + */ + public function __construct(Extractor $extractor) + { + $this->extractor = $extractor; + } + + /** + * @return mixed + */ + public function get() + { + if (!isset($this->cache['cached'])) { + $this->cache = [ + 'cached' => true, + 'value' => $this->detect(), + ]; + } + + return $this->cache['value']; + } + + /** + * @return mixed + */ + abstract public function detect(); +} diff --git a/src/Detectors/Favicon.php b/src/Detectors/Favicon.php new file mode 100644 index 00000000..2e0b1930 --- /dev/null +++ b/src/Detectors/Favicon.php @@ -0,0 +1,30 @@ + + */ +class Favicon extends Detector +{ + public function detect(): UriInterface + { + $document = $this->extractor->getDocument(); + + $result = $document->link('shortcut icon'); + if ($result !== null) { + return $result; + } + + $result = $document->link('icon'); + if ($result !== null) { + return $result; + } + + return $this->extractor->getUri()->withPath('/favicon.ico')->withQuery(''); + } +} diff --git a/src/Detectors/Feeds.php b/src/Detectors/Feeds.php new file mode 100644 index 00000000..b00c2051 --- /dev/null +++ b/src/Detectors/Feeds.php @@ -0,0 +1,40 @@ + + */ +class Feeds extends Detector +{ + /** @var string[] */ + private static array $types = [ + 'application/atom+xml', + 'application/json', + 'application/rdf+xml', + 'application/rss+xml', + 'application/xml', + 'text/xml', + ]; + + /** + * @return \Psr\Http\Message\UriInterface[] + */ + public function detect(): array + { + $document = $this->extractor->getDocument(); + $feeds = []; + + foreach (self::$types as $type) { + $href = $document->link('alternate', ['type' => $type]); + + if ($href !== null) { + $feeds[] = $href; + } + } + + return $feeds; + } +} diff --git a/src/Detectors/Icon.php b/src/Detectors/Icon.php new file mode 100644 index 00000000..eae81474 --- /dev/null +++ b/src/Detectors/Icon.php @@ -0,0 +1,40 @@ + + */ +class Icon extends Detector +{ + public function detect(): ?UriInterface + { + $document = $this->extractor->getDocument(); + + $result = $document->link('apple-touch-icon-precomposed'); + if ($result !== null) { + return $result; + } + + $result = $document->link('apple-touch-icon'); + if ($result !== null) { + return $result; + } + + $result = $document->link('icon', ['sizes' => '144x144']); + if ($result !== null) { + return $result; + } + + $result = $document->link('icon', ['sizes' => '96x96']); + if ($result !== null) { + return $result; + } + + return $document->link('icon', ['sizes' => '48x48']); + } +} diff --git a/src/Detectors/Image.php b/src/Detectors/Image.php new file mode 100644 index 00000000..10c7ae70 --- /dev/null +++ b/src/Detectors/Image.php @@ -0,0 +1,68 @@ + + */ +class Image extends Detector +{ + public function detect(): ?UriInterface + { + $oembed = $this->extractor->getOEmbed(); + $document = $this->extractor->getDocument(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + $result = $oembed->url('http://github.com/image'); + if ($result !== null) { + return $result; + } + + $result = $oembed->url('http://github.com/thumbnail'); + if ($result !== null) { + return $result; + } + + $result = $oembed->url('http://github.com/thumbnail_url'); + if ($result !== null) { + return $result; + } + + $result = $metas->url('/service/og:image', 'og:image:url', 'og:image:secure_url', 'twitter:image', 'twitter:image:src', 'lp:image'); + if ($result !== null) { + return $result; + } + + $result = $document->link('image_src'); + if ($result !== null) { + return $result; + } + + $result = $ld->url('http://github.com/image.url'); + if ($result !== null) { + return $result; + } + + return $this->detectFromContentType(); + } + + private function detectFromContentType(): ?\Psr\Http\Message\UriInterface + { + if (!$this->extractor->getResponse()->hasHeader('content-type')) { + return null; + } + + $contentType = $this->extractor->getResponse()->getHeader('content-type')[0]; + + if (strpos($contentType, 'image/') === 0) { + return $this->extractor->getUri(); + } + + return null; + } +} diff --git a/src/Detectors/Keywords.php b/src/Detectors/Keywords.php new file mode 100644 index 00000000..472c9ed7 --- /dev/null +++ b/src/Detectors/Keywords.php @@ -0,0 +1,75 @@ + + */ +class Keywords extends Detector +{ + /** + * @return string[] + */ + public function detect(): array + { + $tags = []; + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + $types = [ + 'keywords', + 'og:video:tag', + 'og:article:tag', + 'og:video:tag', + 'og:book:tag', + 'lp.article:section', + 'dcterms.subject', + ]; + + foreach ($types as $type) { + $value = $metas->strAll($type); + + if ($value !== []) { + $tags = array_merge($tags, self::toArray($value)); + } + } + + $value = $ld->strAll('keywords'); + + if ($value !== []) { + $tags = array_merge($tags, self::toArray($value)); + } + + /** @var array */ + $tags = array_map('mb_strtolower', $tags); + $tags = array_unique($tags); + $tags = array_filter($tags, fn ($value) => $value !== '' && $value !== '0'); + $tags = array_values($tags); + + return $tags; + } + + /** + * @param string[] $keywords + * @return string[] + */ + private static function toArray(array $keywords): array + { + $all = []; + + foreach ($keywords as $keyword) { + $tags = explode(',', $keyword); + $tags = array_map('trim', $tags); + $tags = array_filter( + $tags, + fn ($value) => $value !== '' && $value !== '0' && substr($value, -3) !== '...' + ); + + $all = array_merge($all, $tags); + } + + return $all; + } +} diff --git a/src/Detectors/Language.php b/src/Detectors/Language.php new file mode 100644 index 00000000..b8dd1e49 --- /dev/null +++ b/src/Detectors/Language.php @@ -0,0 +1,40 @@ + + */ +class Language extends Detector +{ + public function detect(): ?string + { + $document = $this->extractor->getDocument(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + $result = $document->select('/html')->str('lang'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + $result = $document->select('/html')->str('xml:lang'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + $result = $metas->str('language', 'lang', 'og:locale', 'dc:language'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + $result = $document->select('.//meta', ['http-equiv' => 'content-language'])->str('content'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + return $ld->str('inLanguage'); + } +} diff --git a/src/Detectors/Languages.php b/src/Detectors/Languages.php new file mode 100644 index 00000000..5f899c11 --- /dev/null +++ b/src/Detectors/Languages.php @@ -0,0 +1,39 @@ + + */ +class Languages extends Detector +{ + /** + * @return array + */ + public function detect(): array + { + $document = $this->extractor->getDocument(); + $languages = []; + + foreach ($document->select('.//link[@hreflang]')->nodes() as $node) { + if (!$node instanceof \DOMElement) { + continue; + } + + $language = $node->getAttribute('hreflang'); + $href = $node->getAttribute('href'); + + if (isEmpty($language, $href)) { + continue; + } + + $languages[$language] = $this->extractor->resolveUri($href); + } + + return $languages; + } +} diff --git a/src/Detectors/License.php b/src/Detectors/License.php new file mode 100644 index 00000000..a9cf26df --- /dev/null +++ b/src/Detectors/License.php @@ -0,0 +1,20 @@ + + */ +class License extends Detector +{ + public function detect(): ?string + { + $oembed = $this->extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + $license = $oembed->str('license_url'); + return $license !== null ? $license : $metas->str('copyright'); + } +} diff --git a/src/Detectors/ProviderName.php b/src/Detectors/ProviderName.php new file mode 100644 index 00000000..1340aa7b --- /dev/null +++ b/src/Detectors/ProviderName.php @@ -0,0 +1,74 @@ + + */ +class ProviderName extends Detector +{ + /** @var string[] */ + private static array $suffixes; + + public function detect(): string + { + $oembed = $this->extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + $result = $oembed->str('provider_name'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + $result = $metas->str( + 'og:site_name', + 'dcterms.publisher', + 'publisher', + 'article:publisher' + ); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + return ucfirst($this->fallback()); + } + + private function fallback(): string + { + $host = $this->extractor->getUri()->getHost(); + + $host = array_reverse(explode('.', $host)); + + switch (count($host)) { + case 1: + return $host[0]; + case 2: + return $host[1]; + default: + $tld = $host[1].'.'.$host[0]; + $suffixes = self::getSuffixes(); + + if (in_array($tld, $suffixes, true)) { + return $host[2]; + } + + return $host[1]; + } + } + + /** + * @return string[] + */ + private static function getSuffixes(): array + { + if (!isset(self::$suffixes)) { + /** @var string[] */ + $suffixes = require dirname(__DIR__).'/resources/suffix.php'; + self::$suffixes = $suffixes; + } + + return self::$suffixes; + } +} diff --git a/src/Detectors/ProviderUrl.php b/src/Detectors/ProviderUrl.php new file mode 100644 index 00000000..9201179b --- /dev/null +++ b/src/Detectors/ProviderUrl.php @@ -0,0 +1,36 @@ + + */ +class ProviderUrl extends Detector +{ + public function detect(): UriInterface + { + $oembed = $this->extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + + $result = $oembed->url('http://github.com/provider_url'); + if ($result !== null) { + return $result; + } + + $result = $metas->url('/service/og:website'); + if ($result !== null) { + return $result; + } + + return $this->fallback(); + } + + private function fallback(): UriInterface + { + return $this->extractor->getUri()->withPath('')->withQuery('')->withFragment(''); + } +} diff --git a/src/Detectors/PublishedTime.php b/src/Detectors/PublishedTime.php new file mode 100644 index 00000000..c6ed932d --- /dev/null +++ b/src/Detectors/PublishedTime.php @@ -0,0 +1,81 @@ + + */ +class PublishedTime extends Detector +{ + public function detect(): ?DateTime + { + $oembed = $this->extractor->getOEmbed(); + $metas = $this->extractor->getMetas(); + $ld = $this->extractor->getLinkedData(); + + $result = $oembed->time('pubdate'); + if ($result !== null) { + return $result; + } + + $result = $metas->time( + 'article:published_time', + 'created', + 'date', + 'datepublished', + 'music:release_date', + 'video:release_date', + 'newsrepublic:publish_date' + ); + if ($result !== null) { + return $result; + } + + $result = $ld->time( + 'pagePublished', + 'datePublished' + ); + if ($result !== null) { + return $result; + } + + $result = $this->detectFromPath(); + if ($result !== null) { + return $result; + } + + return $metas->time( + 'pagerender', + 'pub_date', + 'publication-date', + 'lp.article:published_time', + 'lp.article:modified_time', + 'publish-date', + 'rc.datecreation', + 'timestamp', + 'sailthru.date', + 'article:modified_time', + 'dcterms.date' + ); + } + + /** + * Some sites using WordPress have the published time in the url + * For example: mysite.com/2020/05/19/post-title + */ + private function detectFromPath(): ?DateTime + { + $path = $this->extractor->getUri()->getPath(); + + if (preg_match('#/(19|20)\d{2}/[0-1]?\d/[0-3]?\d/#', $path, $matches) === 1) { + $date = date_create_from_format('/Y/m/d/', $matches[0]); + return $date !== false ? $date : null; + } + + return null; + } +} diff --git a/src/Detectors/Redirect.php b/src/Detectors/Redirect.php new file mode 100644 index 00000000..1f18437f --- /dev/null +++ b/src/Detectors/Redirect.php @@ -0,0 +1,30 @@ + + */ +class Redirect extends Detector +{ + public function detect(): ?UriInterface + { + $document = $this->extractor->getDocument(); + $value = $document->select('.//meta', ['http-equiv' => 'refresh'])->str('content'); + + return $value !== null ? $this->extract($value) : null; + } + + private function extract(string $value): ?UriInterface + { + if (preg_match('/url=(.+)$/i', $value, $match) === 1) { + return $this->extractor->resolveUri(trim($match[1], '\'"')); + } + + return null; + } +} diff --git a/src/Detectors/Title.php b/src/Detectors/Title.php new file mode 100644 index 00000000..7f38b006 --- /dev/null +++ b/src/Detectors/Title.php @@ -0,0 +1,39 @@ + + */ +class Title extends Detector +{ + public function detect(): ?string + { + $oembed = $this->extractor->getOEmbed(); + $document = $this->extractor->getDocument(); + $metas = $this->extractor->getMetas(); + + $result = $oembed->str('title'); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + $result = $metas->str( + 'og:title', + 'twitter:title', + 'lp:title', + 'dcterms.title', + 'article:title', + 'headline', + 'article.headline', + 'parsely-title' + ); + if (is_string($result) && trim($result) !== '') { + return $result; + } + + return $document->select('.//head/title')->str(); + } +} diff --git a/src/Detectors/Url.php b/src/Detectors/Url.php new file mode 100644 index 00000000..7771eef6 --- /dev/null +++ b/src/Detectors/Url.php @@ -0,0 +1,30 @@ + + */ +class Url extends Detector +{ + public function detect(): UriInterface + { + $oembed = $this->extractor->getOEmbed(); + + $result = $oembed->http://github.com/url('url'); + if ($result !== null) { + return $result; + } + + $result = $oembed->url('http://github.com/web_page'); + if ($result !== null) { + return $result; + } + + return $this->extractor->getUri(); + } +} diff --git a/src/Document.php b/src/Document.php new file mode 100644 index 00000000..3a99dfa0 --- /dev/null +++ b/src/Document.php @@ -0,0 +1,190 @@ +extractor = $extractor; + + $html = (string) $extractor->getResponse()->getBody(); + $html = str_replace('
', "\n
", $html); + $html = str_replace('
getResponse()->getHeaderLine('content-type'); + preg_match('/charset=(?:"|\')?(.*?)(?=$|\s|;|"|\'|>)/i', $contentType, $match); + if (isset($match[1]) && $match[1] !== '' && $match[1] !== '0') { + $encoding = trim($match[1], ','); + $encoding = $this->getValidEncoding($encoding); + } + if (is_null($encoding) && $html !== '') { + preg_match('/charset=(?:"|\')?(.*?)(?=$|\s|;|"|\'|>)/i', $html, $match); + if (isset($match[1]) && $match[1] !== '' && $match[1] !== '0') { + $encoding = trim($match[1], ','); + $encoding = $this->getValidEncoding($encoding); + } + } + $this->document = $html !== '' ? Parser::parse($html, $encoding) : new DOMDocument(); + $this->initXPath(); + } + + /** + * Get valid encoding name if it exists, otherwise return null + * + * Uses mb_encoding_aliases() to verify the encoding is valid. + * + * TODO: When dropping PHP 7.4 support, remove the PHP_VERSION_ID < 80000 branch. + * PHP version differences: + * - PHP 7.4: mb_encoding_aliases() returns false for invalid encoding and throws Warning for empty string + * - PHP 8.0+: mb_encoding_aliases() throws ValueError for invalid/empty encoding + * + * @see https://www.php.net/manual/en/function.mb-encoding-aliases.php + */ + private function getValidEncoding(?string $encoding): ?string + { + if (PHP_VERSION_ID < 80000) { + // PHP 7.4: Check return value (false = invalid encoding) + // Need to check null/empty first to avoid Warning + // TODO: Remove this entire branch when PHP 7.4 support is dropped + if ($encoding === null || $encoding === '') { + return null; + } + $ret = @mb_encoding_aliases($encoding); + /** @phpstan-ignore function.alreadyNarrowedType (PHP 7.4 returns false for invalid encoding, PHP 8.0+ returns array) */ + return is_array($ret) ? $encoding : null; + } else { + // PHP 8.0+: ValueError exception is thrown for invalid/empty encoding + try { + $aliases = mb_encoding_aliases($encoding ?? ''); + // If mb_encoding_aliases succeeds, return the input value as is. Some encodings do not have aliases. + return $encoding; + } catch (\ValueError $exception) { + return null; + } + } + } + + private function initXPath(): void + { + $this->xpath = new DOMXPath($this->document); + $this->xpath->registerNamespace('php', 'http://php.net/xpath'); + $this->xpath->registerPhpFunctions(); + } + + public function __clone() + { + $this->document = clone $this->document; + $this->initXPath(); + } + + public function remove(string $query): void + { + $result = $this->xpath->query($query); + if ($result === false) { + return; + } + $nodes = iterator_to_array($result, false); + + foreach ($nodes as $node) { + if ($node->parentNode !== null) { + $node->parentNode->removeChild($node); // @phpstan-ignore argument.type + } + } + } + + public function removeCss(string $query): void + { + $this->remove(self::cssToXpath($query)); + } + + public function getDocument(): DOMDocument + { + return $this->document; + } + + /** + * Helper to build xpath queries easily and case insensitive + * + * @param array $attributes + */ + private static function buildQuery(string $startQuery, array $attributes): string + { + $selector = [$startQuery]; + + foreach ($attributes as $name => $value) { + $selector[] = sprintf('[php:functionString("strtolower", @%s)="%s"]', $name, mb_strtolower($value)); + } + + return implode('', $selector); + } + + /** + * Select a element in the dom + * + * @param array|null $attributes + */ + public function select(string $query, ?array $attributes = null, ?DOMNode $context = null): QueryResult + { + if ($attributes !== null && $attributes !== []) { + $query = self::buildQuery($query, $attributes); + } + + $result = $this->xpath->query($query, $context); + if ($result === false) { + $result = new \DOMNodeList(); + } + return new QueryResult($result, $this->extractor); // @phpstan-ignore argument.type + } + + /** + * Select a element in the dom using a css selector + */ + public function selectCss(string $query, ?DOMNode $context = null): QueryResult + { + return $this->select(self::cssToXpath($query), null, $context); + } + + /** + * Shortcut to select a element and return the href + * + * @param array $extra + */ + public function link(string $rel, array $extra = []): ?UriInterface + { + return $this->select('.//link', ['rel' => $rel] + $extra)->url('http://github.com/href'); + } + + public function __toString(): string + { + return Parser::stringify($this->getDocument()); + } + + private static function cssToXpath(string $selector): string + { + if (!isset(self::$cssConverter)) { + if (!class_exists(CssSelectorConverter::class)) { + throw new RuntimeException('You need to install "symfony/css-selector" to use css selectors'); + } + + self::$cssConverter = new CssSelectorConverter(); + } + + return self::$cssConverter->toXPath($selector); + } +} diff --git a/src/Embed.php b/src/Embed.php index 3d096785..6f2d583a 100644 --- a/src/Embed.php +++ b/src/Embed.php @@ -1,133 +1,106 @@ crawler = $crawler !== null ? $crawler : new Crawler(); + $this->extractorFactory = $extractorFactory !== null ? $extractorFactory : new ExtractorFactory(); + } + + public function get(string $url): Extractor + { + $request = $this->crawler->createRequest('GET', $url); + $response = $this->crawler->sendRequest($request); + + return $this->extract($request, $response); + } + /** - * Gets the info from an url. - * - * @param string|Request $request The url or a request with the url - * @param array $config Options passed to the adapter - * - * @throws Exceptions\InvalidUrlException If the urls is not valid - * @throws \InvalidArgumentException If any config argument is not valid - * - * @return AdapterInterface + * @return Extractor[] */ - public static function create($request, array $config = array()) + public function getMulti(string ...$urls): array { - $request = self::getRequest($request, isset($config['resolver']) ? $config['resolver'] : null); + $requests = array_map( + fn ($url) => $this->crawler->createRequest('GET', $url), + $urls + ); - //Use custom adapter - if (!empty($config['adapter']['class'])) { - if (($info = self::executeAdapter($config['adapter']['class'], $request, $config))) { - return $info; - } - } - - //If is a file use File Adapter - if (($info = self::executeAdapter('Embed\Adapters\File', $request, $config))) { - return $info; - } + $responses = $this->crawler->sendRequests(...$requests); - //Search the adapter using the domain - $adapter = 'Embed\\Adapters\\'.$request->getClassNameForDomain(); + $return = []; - if (class_exists($adapter) && ($info = self::executeAdapter($adapter, $request, $config))) { - return $info; + foreach ($responses as $k => $response) { + /** @phpstan-ignore instanceof.alwaysTrue (defensive check for error handling) */ + if ($response instanceof ResponseInterface) { + $return[] = $this->extract($requests[$k], $response); + } } - //Use the standard webpage adapter - if (($info = self::executeAdapter('Embed\Adapters\Webpage', $request, $config))) { - return $info; - } + return $return; + } - if (!$request->isValid()) { - throw new Exceptions\InvalidUrlException("The url '{$request->getUrl()}' returns the http code '{$request->getHttpCode()}'"); - } + public function getCrawler(): Crawler + { + return $this->crawler; + } - throw new Exceptions\InvalidUrlException("The url '{$request->getUrl()}' is not supported"); + public function getExtractorFactory(): ExtractorFactory + { + return $this->extractorFactory; } /** - * Gets the info from a source (list of urls). - * - * @param string|Request $request The url or a request with the source url - * @param null|array $config Options passed to the adapter - * - * @return false|Sources\SourceInterface + * @param array $settings */ - public static function createSource($request, array $config = null) + public function setSettings(array $settings): void { - $request = self::getRequest($request, $config); + $this->extractorFactory->setSettings($settings); + } - if (!$request->isValid()) { - return false; + private function extract(RequestInterface $request, ResponseInterface $response, bool $redirect = true): Extractor + { + $uri = $this->crawler->getResponseUri($response); + if ($uri === null) { + $uri = $request->getUri(); } - //If is a xml feed (rss/atom) - if (Sources\Feed::check($request)) { - $sources = new Sources\Feed($request); + $extractor = $this->extractorFactory->createExtractor($uri, $request, $response, $this->crawler); - if ($sources->isValid()) { - return $sources; - } + if (!$redirect || !$this->mustRedirect($extractor)) { + return $extractor; } - return false; - } - - /** - * Execute an adapter. - * - * @param string $adapter Adapter class name - * @param Request $request - * @param null|array $config - * - * @throws \InvalidArgumentException If the adapter class in not AdapterInterface - * - * @return false|AdapterInterface - */ - private static function executeAdapter($adapter, Request $request, array $config = null) - { - if (!in_array('Embed\\Adapters\\AdapterInterface', class_implements($adapter))) { - throw new \InvalidArgumentException("The class '$adapter' must implements 'Embed\\Adapters\\AdapterInterface'"); + // Magic property access returns mixed, but we know it's ?UriInterface from Redirect detector + $redirectUri = $extractor->redirect; + if (!($redirectUri instanceof \Psr\Http\Message\UriInterface)) { + return $extractor; } - if (call_user_func([$adapter, 'check'], $request)) { - return new $adapter($request, $config); - } + $request = $this->crawler->createRequest('GET', (string) $redirectUri); + $response = $this->crawler->sendRequest($request); - return false; + return $this->extract($request, $response, false); } - /** - * Init a request. - * - * @param string|Request $request The url or a request with the url - * @param null|array $config Options passed to the adapter - * - * @throws \InvalidArgumentException If the class in not Embed\Request instance - * - * @return Request - */ - private static function getRequest($request, array $config = null) + private function mustRedirect(Extractor $extractor): bool { - if (is_string($request)) { - return new Request( - $request, - isset($config['class']) ? $config['class'] : null, - isset($config['config']) ? $config['config'] : [] - ); - } - - if (!($request instanceof Request)) { - throw new \InvalidArgumentException('Embed::create only accepts instances of Embed\\Request or strings'); + if ($extractor->getOEmbed()->all() !== []) { + return false; } - return $request; + // Magic property access returns mixed, but we know it's ?UriInterface from Redirect detector + $redirectUri = $extractor->redirect; + return $redirectUri instanceof \Psr\Http\Message\UriInterface; } } diff --git a/src/EmbedCode.php b/src/EmbedCode.php new file mode 100644 index 00000000..250657e4 --- /dev/null +++ b/src/EmbedCode.php @@ -0,0 +1,42 @@ +html = $html; + $this->width = $width; + $this->height = $height; + + if ($width !== null && $width !== 0 && $height !== null && $height !== 0) { + $this->ratio = round(($height / $width) * 100, 3); + } + } + + public function __toString(): string + { + return $this->html; + } + + #[ReturnTypeWillChange] + public function jsonSerialize() + { + return [ + 'html' => $this->html, + 'width' => $this->width, + 'height' => $this->height, + 'ratio' => $this->ratio, + ]; + } +} diff --git a/src/Exceptions/EmbedException.php b/src/Exceptions/EmbedException.php deleted file mode 100644 index 5cf7ffc6..00000000 --- a/src/Exceptions/EmbedException.php +++ /dev/null @@ -1,9 +0,0 @@ - */ + private array $settings = []; + /** @var array> */ + private array $customDetectors = []; + /** @var AuthorName<$this> */ + protected AuthorName $authorName; + /** @var AuthorUrl<$this> */ + protected AuthorUrl $authorUrl; + /** @var Cms<$this> */ + protected Cms $cms; + /** @var Code<$this> */ + protected Code $code; + /** @var Description<$this> */ + protected Description $description; + /** @var Favicon<$this> */ + protected Favicon $favicon; + /** @var Feeds<$this> */ + protected Feeds $feeds; + /** @var Icon<$this> */ + protected Icon $icon; + /** @var Image<$this> */ + protected Image $image; + /** @var Keywords<$this> */ + protected Keywords $keywords; + /** @var Language<$this> */ + protected Language $language; + /** @var Languages<$this> */ + protected Languages $languages; + /** @var License<$this> */ + protected License $license; + /** @var ProviderName<$this> */ + protected ProviderName $providerName; + /** @var ProviderUrl<$this> */ + protected ProviderUrl $providerUrl; + /** @var PublishedTime<$this> */ + protected PublishedTime $publishedTime; + /** @var Redirect<$this> */ + protected Redirect $redirect; + /** @var Title<$this> */ + protected Title $title; + /** @var Url<$this> */ + protected Url $url; + + public function __construct(UriInterface $uri, RequestInterface $request, ResponseInterface $response, Crawler $crawler) + { + $this->uri = $uri; + $this->request = $request; + $this->response = $response; + $this->crawler = $crawler; + + //APIs + $this->document = new Document($this); + $this->oembed = new OEmbed($this); + $this->linkedData = new LinkedData($this); + $this->metas = new Metas($this); + + //Detectors + $this->authorName = new AuthorName($this); + $this->authorUrl = new AuthorUrl($this); + $this->cms = new Cms($this); + $this->code = new Code($this); + $this->description = new Description($this); + $this->favicon = new Favicon($this); + $this->feeds = new Feeds($this); + $this->icon = new Icon($this); + $this->image = new Image($this); + $this->keywords = new Keywords($this); + $this->language = new Language($this); + $this->languages = new Languages($this); + $this->license = new License($this); + $this->providerName = new ProviderName($this); + $this->providerUrl = new ProviderUrl($this); + $this->publishedTime = new PublishedTime($this); + $this->redirect = new Redirect($this); + $this->title = new Title($this); + $this->url = new Url($this); + } + + /** + * @return mixed + */ + public function __get(string $name) + { + $detector = $this->customDetectors[$name] ?? null; + + if ($detector === null && property_exists($this, $name)) { + /** @var mixed $property */ + /** @phpstan-ignore property.dynamicName */ + $property = (fn($n) => $this->$n)($name); + if ($property instanceof Detector) { + $detector = $property; + } + } + + if ($detector === null) { + throw new DomainException(sprintf('Invalid key "%s". No detector found for this value', $name)); + } + + return $detector->get(); + } + + /** + * @return array + */ + public function createCustomDetectors(): array + { + return []; + } + + /** + * @phpstan-param Detector<$this> $detector + */ + public function addDetector(string $name, Detector $detector): void + { + $this->customDetectors[$name] = $detector; + } + + /** + * @param array $settings + */ + public function setSettings(array $settings): void + { + $this->settings = $settings; + } + + /** + * @return array + */ + public function getSettings(): array + { + return $this->settings; + } + + /** + * @return mixed + */ + public function getSetting(string $key) + { + return $this->settings[$key] ?? null; + } + + public function getDocument(): Document + { + return $this->document; + } + + public function getOEmbed(): OEmbed + { + return $this->oembed; + } + + public function getLinkedData(): LinkedData + { + return $this->linkedData; + } + + public function getMetas(): Metas + { + return $this->metas; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } + + public function getResponse(): ResponseInterface + { + return $this->response; + } + + public function getUri(): UriInterface + { + return $this->uri; + } + + /** + * @param UriInterface|string $uri + */ + public function resolveUri($uri): UriInterface + { + if (is_string($uri)) { + if (!isHttp($uri)) { + throw new InvalidArgumentException(sprintf('Uri string must use http or https scheme (%s)', $uri)); + } + + $uri = $this->crawler->createUri($uri); + } + + return resolveUri($this->uri, $uri); + } + + public function getCrawler(): Crawler + { + return $this->crawler; + } +} diff --git a/src/ExtractorFactory.php b/src/ExtractorFactory.php new file mode 100644 index 00000000..dc43daa2 --- /dev/null +++ b/src/ExtractorFactory.php @@ -0,0 +1,120 @@ + */ + private string $default = Extractor::class; + /** @var array> */ + private array $adapters = [ + 'slides.com' => Adapters\Slides\Extractor::class, + 'pinterest.com' => Adapters\Pinterest\Extractor::class, + 'flickr.com' => Adapters\Flickr\Extractor::class, + 'snipplr.com' => Adapters\Snipplr\Extractor::class, + 'play.cadenaser.com' => Adapters\CadenaSer\Extractor::class, + 'ideone.com' => Adapters\Ideone\Extractor::class, + 'gist.github.com' => Adapters\Gist\Extractor::class, + 'github.com' => Adapters\Github\Extractor::class, + 'wikipedia.org' => Adapters\Wikipedia\Extractor::class, + 'archive.org' => Adapters\Archive\Extractor::class, + 'sassmeister.com' => Adapters\Sassmeister\Extractor::class, + 'facebook.com' => Adapters\Facebook\Extractor::class, + 'instagram.com' => Adapters\Instagram\Extractor::class, + 'imageshack.com' => Adapters\ImageShack\Extractor::class, + 'youtube.com' => Adapters\Youtube\Extractor::class, + 'twitch.tv' => Adapters\Twitch\Extractor::class, + 'bandcamp.com' => Adapters\Bandcamp\Extractor::class, + 'twitter.com' => Adapters\Twitter\Extractor::class, + 'x.com' => Adapters\Twitter\Extractor::class, + ]; + /** @var array>> */ + private array $customDetectors = []; + /** @var array */ + private array $settings; + + /** + * @param array|null $settings + */ + public function __construct(?array $settings = []) + { + $this->settings = $settings ?? []; + } + + public function createExtractor(UriInterface $uri, RequestInterface $request, ResponseInterface $response, Crawler $crawler): Extractor + { + $host = $uri->getHost(); + $class = $this->default; + + foreach ($this->adapters as $adapterHost => $adapter) { + // Check if $host is the same domain as $adapterHost. + if ($host === $adapterHost) { + $class = $adapter; + break; + } + + // Check if $host is a subdomain of $adapterHost. + if (substr($host, -strlen($adapterHost) - 1) === ".{$adapterHost}") { + $class = $adapter; + break; + } + } + + $extractor = new $class($uri, $request, $response, $crawler); + $extractor->setSettings($this->settings); + + foreach ($this->customDetectors as $name => $detectorClass) { + $detector = new $detectorClass($extractor); + $extractor->addDetector($name, $detector); + } + + foreach ($extractor->createCustomDetectors() as $name => $detector) { + $extractor->addDetector($name, $detector); + } + + return $extractor; + } + + /** + * @param class-string $class + */ + public function addAdapter(string $pattern, string $class): void + { + $this->adapters[$pattern] = $class; + } + + /** + * @param class-string> $class + */ + public function addDetector(string $name, string $class): void + { + $this->customDetectors[$name] = $class; + } + + public function removeAdapter(string $pattern): void + { + unset($this->adapters[$pattern]); + } + + /** + * @param class-string $class + */ + public function setDefault(string $class): void + { + $this->default = $class; + } + + /** + * @param array $settings + */ + public function setSettings(array $settings): void + { + $this->settings = $settings; + } +} diff --git a/src/GetTrait.php b/src/GetTrait.php deleted file mode 100644 index 4baaf97b..00000000 --- a/src/GetTrait.php +++ /dev/null @@ -1,26 +0,0 @@ -sourceUrl executes $source->getSourceUrl(). - * - * @param string $name The property name - * - * @return mixed - */ - public function __get($name) - { - $method = 'get'.$name; - - if (method_exists($this, $method)) { - return $this->$name = $this->$method(); - } - } -} diff --git a/src/Http/Crawler.php b/src/Http/Crawler.php new file mode 100644 index 00000000..2c233636 --- /dev/null +++ b/src/Http/Crawler.php @@ -0,0 +1,84 @@ + */ + private array $defaultHeaders = [ + 'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:73.0) Gecko/20100101 Firefox/73.0', + 'Cache-Control' => 'max-age=0', + ]; + + public function __construct(?ClientInterface $client = null, ?RequestFactoryInterface $requestFactory = null, ?UriFactoryInterface $uriFactory = null) + { + $this->client = $client !== null ? $client : new CurlClient(); + $this->requestFactory = $requestFactory !== null ? $requestFactory : FactoryDiscovery::getRequestFactory(); + $this->uriFactory = $uriFactory !== null ? $uriFactory : FactoryDiscovery::getUriFactory(); + } + + /** + * @param array $headers + */ + public function addDefaultHeaders(array $headers): void + { + $this->defaultHeaders = $headers + $this->defaultHeaders; + } + + /** + * @param UriInterface|string $uri The URI associated with the request. + */ + public function createRequest(string $method, $uri): RequestInterface + { + $request = $this->requestFactory->createRequest($method, $uri); + + foreach ($this->defaultHeaders as $name => $value) { + $request = $request->withHeader($name, $value); + } + + return $request; + } + + public function createUri(string $uri = ''): UriInterface + { + return $this->uriFactory->createUri($uri); + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->client->sendRequest($request); + } + + /** + * @return array + */ + public function sendRequests(RequestInterface ...$requests): array + { + if ($this->client instanceof CurlClient) { + return $this->client->sendRequests(...$requests); + } + + return array_map( + fn ($request) => $this->client->sendRequest($request), + $requests + ); + } + + public function getResponseUri(ResponseInterface $response): ?UriInterface + { + $location = $response->getHeaderLine('Content-Location'); + + return $location !== '' ? $this->uriFactory->createUri($location) : null; + } +} diff --git a/src/Http/CurlClient.php b/src/Http/CurlClient.php new file mode 100644 index 00000000..9794d718 --- /dev/null +++ b/src/Http/CurlClient.php @@ -0,0 +1,47 @@ + */ + private array $settings = []; + + public function __construct(?ResponseFactoryInterface $responseFactory = null) + { + $this->responseFactory = $responseFactory !== null ? $responseFactory : FactoryDiscovery::getResponseFactory(); + } + + /** + * @param array $settings + */ + public function setSettings(array $settings): void + { + $this->settings = $settings + $this->settings; + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + $responses = CurlDispatcher::fetch($this->settings, $this->responseFactory, $request); + + return $responses[0]; + } + + /** + * @return ResponseInterface[] + */ + public function sendRequests(RequestInterface ...$request): array + { + return CurlDispatcher::fetch($this->settings, $this->responseFactory, ...$request); + } +} diff --git a/src/Http/CurlDispatcher.php b/src/Http/CurlDispatcher.php new file mode 100644 index 00000000..6cdde3a1 --- /dev/null +++ b/src/Http/CurlDispatcher.php @@ -0,0 +1,272 @@ + */ + private array $headers = []; + private bool $isBinary = false; + private ?StreamInterface $body = null; + private ?int $error = null; + /** @var array */ + private array $settings; + + /** + * @param array $settings + * @return ResponseInterface[] + */ + public static function fetch(array $settings, ResponseFactoryInterface $responseFactory, RequestInterface ...$requests): array + { + if (count($requests) === 1) { + $connection = new static($settings, $requests[0]); + /** @var resource|\CurlHandle $curlHandle */ + $curlHandle = $connection->curl; + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + curl_exec($curlHandle); + return [$connection->getResponse($responseFactory)]; + } + + //Init connections + $multi = curl_multi_init(); + $connections = []; + + foreach ($requests as $request) { + $connection = new static($settings, $request); + /** @var resource|\CurlHandle $curlHandle */ + $curlHandle = $connection->curl; + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + curl_multi_add_handle($multi, $curlHandle); + + $connections[] = $connection; + } + + //Run + $active = null; + do { + $status = curl_multi_exec($multi, $active); + + if ($active) { + curl_multi_select($multi); + } + + $info = curl_multi_info_read($multi); + + if (is_array($info) && isset($info['handle'], $info['result'])) { + $result = $info['result']; + // Validate and cast result to int, only set if it's a non-success error code + if (is_numeric($result)) { + $errorCode = (int) $result; + if ($errorCode !== CURLE_OK) { + foreach ($connections as $connection) { + if ($connection->curl === $info['handle']) { + $connection->error = $errorCode; + break; + } + } + } + } + } + } while ($active && $status === CURLM_OK); + + //Close connections + foreach ($connections as $connection) { + /** @var resource|\CurlHandle $curlHandle */ + $curlHandle = $connection->curl; + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + curl_multi_remove_handle($multi, $curlHandle); + } + + curl_multi_close($multi); + + return array_map( + fn ($connection) => $connection->getResponse($responseFactory), + $connections + ); + } + + /** + * @param array $settings + */ + private function __construct(array $settings, RequestInterface $request, ?StreamFactoryInterface $streamFactory = null) + { + $this->request = $request; + $this->curl = curl_init((string) $request->getUri()); + $this->settings = $settings; + $this->streamFactory = $streamFactory ?? FactoryDiscovery::getStreamFactory(); + + $cookies = $settings['cookies_path'] ?? str_replace('//', '/', sys_get_temp_dir().'/embed-cookies.txt'); + + curl_setopt_array($this->curl, [ + CURLOPT_HTTPHEADER => $this->getRequestHeaders(), + CURLOPT_POST => strtoupper($request->getMethod()) === 'POST', + CURLOPT_MAXREDIRS => $settings['max_redirs'] ?? 10, + CURLOPT_CONNECTTIMEOUT => $settings['connect_timeout'] ?? 10, + CURLOPT_TIMEOUT => $settings['timeout'] ?? 10, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYHOST => $settings['ssl_verify_host'] ?? 0, + CURLOPT_SSL_VERIFYPEER => $settings['ssl_verify_peer'] ?? false, + CURLOPT_ENCODING => '', + CURLOPT_CAINFO => CaBundle::getSystemCaRootBundlePath(), + CURLOPT_AUTOREFERER => true, + CURLOPT_FOLLOWLOCATION => $settings['follow_location'] ?? true, + CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, + CURLOPT_USERAGENT => $settings['user_agent'] ?? $request->getHeaderLine('User-Agent'), + CURLOPT_COOKIEJAR => $cookies, + CURLOPT_COOKIEFILE => $cookies, + CURLOPT_HEADERFUNCTION => [$this, 'writeHeader'], + CURLOPT_WRITEFUNCTION => [$this, 'writeBody'], + ]); + } + + private function getResponse(ResponseFactoryInterface $responseFactory): ResponseInterface + { + /** @var resource|\CurlHandle $curlHandle */ + $curlHandle = $this->curl; + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + $info = curl_getinfo($curlHandle); + + if ($this->error !== null && $this->error !== 0) { + /** @phpstan-ignore argument.type (curl_strerror returns string|null in some versions) */ + $this->error(curl_strerror($this->error), $this->error); + } + + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + $errno = curl_errno($curlHandle); + if ($errno !== 0) { + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + $this->error(curl_error($curlHandle), $errno); + } + + /** @phpstan-ignore argument.type (PHP 7.4/8.0 compatibility) */ + curl_close($curlHandle); + + $response = $responseFactory->createResponse($info['http_code']); + + foreach ($this->headers as $header) { + list($name, $value) = $header; + $response = $response->withAddedHeader($name, $value); + } + + $response = $response + ->withAddedHeader('Content-Location', $info['url']) + ->withAddedHeader('X-Request-Time', sprintf('%.3f ms', $info['total_time'])); + + if ($this->body !== null) { + //5Mb max + $this->body->rewind(); + $response = $response->withBody($this->body); + $this->body = null; + } + + return $response; + } + + private function error(string $message, int $code): void + { + $ignored = $this->settings['ignored_errors'] ?? null; + + if ($ignored === true || (is_array($ignored) && in_array($code, $ignored, true))) { + return; + } + + if ($this->isBinary && $code === CURLE_WRITE_ERROR) { + // The write callback aborted the request to prevent a download of the binary file + return; + } + + throw new NetworkException($message, $code, $this->request); + } + + /** + * @return array + */ + private function getRequestHeaders(): array + { + $headers = []; + + foreach ($this->request->getHeaders() as $name => $values) { + switch (strtolower($name)) { + case 'user-agent': + break; + default: + $headers[] = $name . ':' . implode(', ', $values); + } + } + + return $headers; + } + + /** + * @param resource|\CurlHandle $curl + * @param mixed $string + */ + private function writeHeader($curl, $string): int + { + if (!is_string($string)) { + return 0; + } + + if (preg_match('/^([\w-]+):(.*)$/', $string, $matches) === 1) { + $name = strtolower($matches[1]); + $value = trim($matches[2]); + $this->headers[] = [$name, $value]; + + if ($name === 'content-type') { + $this->isBinary = preg_match('/(text|html|json)/', strtolower($value)) === 0; + } + } elseif ($this->headers !== []) { + $key = array_key_last($this->headers); + $this->headers[$key][1] .= ' '.trim($string); + } + + return strlen($string); + } + + /** + * @param resource|\CurlHandle $curl + * @param mixed $string + */ + private function writeBody($curl, $string): int + { + if (!is_string($string)) { + return -1; + } + + if ($this->isBinary) { + return -1; + } + + if ($this->body === null) { + $this->body = $this->streamFactory->createStreamFromFile('php://temp', 'w+'); + } + + if ($this->body->getSize() > self::$contentLengthThreshold) { + return strlen($string); + } + + return $this->body->write($string); + } +} diff --git a/src/Http/FactoryDiscovery.php b/src/Http/FactoryDiscovery.php new file mode 100644 index 00000000..993e6435 --- /dev/null +++ b/src/Http/FactoryDiscovery.php @@ -0,0 +1,103 @@ +request = $request; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/src/Http/RequestException.php b/src/Http/RequestException.php new file mode 100644 index 00000000..701d3400 --- /dev/null +++ b/src/Http/RequestException.php @@ -0,0 +1,24 @@ +request = $request; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } +} diff --git a/src/HttpApiTrait.php b/src/HttpApiTrait.php new file mode 100644 index 00000000..8e4180bb --- /dev/null +++ b/src/HttpApiTrait.php @@ -0,0 +1,40 @@ +endpoint; + } + + /** + * @return array + */ + private function fetchJSON(UriInterface $uri): array + { + $crawler = $this->extractor->getCrawler(); + $request = $crawler->createRequest('GET', $uri); + $response = $crawler->sendRequest($request); + + try { + $data = json_decode((string) $response->getBody(), true); + if (is_array($data)) { + /** @var array */ + return $data; + } + return []; + } catch (Exception $exception) { + return []; + } + } +} diff --git a/src/ImageInfo/Curl.php b/src/ImageInfo/Curl.php deleted file mode 100644 index db1b7049..00000000 --- a/src/ImageInfo/Curl.php +++ /dev/null @@ -1,174 +0,0 @@ - 20, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_TIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => 0, - CURLOPT_SSL_VERIFYHOST => 0, - CURLOPT_ENCODING => '', - CURLOPT_AUTOREFERER => true, - CURLOPT_USERAGENT => 'Embed PHP Library', - CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, - ]; - - /** - * {@inheritdoc} - */ - public static function getImagesInfo(array $images, array $config = null) - { - if (empty($images)) { - return []; - } - - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $connections = []; - $curl = curl_multi_init(); - $result = []; - - foreach ($images as $k => $image) { - if (strpos($image['value'], 'data:') === 0) { - if ($info = static::getEmbeddedImageInfo($image['value'])) { - $result[] = array_merge($image, $info); - } - - continue; - } - - $connections[$k] = new static($image['value'], $finfo, $config); - - curl_multi_add_handle($curl, $connections[$k]->getConnection()); - } - - if ($connections) { - do { - $return = curl_multi_exec($curl, $active); - } while ($return === CURLM_CALL_MULTI_PERFORM); - - while ($active && $return === CURLM_OK) { - if (curl_multi_select($curl) === -1) { - usleep(100); - } - - do { - $return = curl_multi_exec($curl, $active); - } while ($return === CURLM_CALL_MULTI_PERFORM); - } - - foreach ($connections as $k => $connection) { - curl_multi_remove_handle($curl, $connection->getConnection()); - - if (($info = $connection->getInfo())) { - $result[] = array_merge($images[$k], $info); - } - } - } - - finfo_close($finfo); - curl_multi_close($curl); - - return $result; - } - - /** - * Init the curl connection. - * - * @param string $url The image url - * @param resource $finfo A fileinfo resource to get the mimetype - * @param null|array $config Custom options for the curl request - */ - public function __construct($url, $finfo, array $config = null) - { - $this->finfo = $finfo; - $this->connection = curl_init(); - - if ($config) { - $this->config = array_replace($this->config, $config); - } - - curl_setopt_array($this->connection, [ - CURLOPT_RETURNTRANSFER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_URL => $url, - CURLOPT_WRITEFUNCTION => [$this, 'writeCallback'], - ] + $this->config); - } - - /** - * Returns the curl resource. - * - * @return resource - */ - public function getConnection() - { - return $this->connection; - } - - /** - * Get the image info with the format [$width, $height, $mimetype]. - * - * @return null|array - */ - public function getInfo() - { - return $this->info; - } - - /** - * Callback used to save the first bytes of the body content. - * - * @param resource $connection - * @param string $string - * - * return integer - */ - public function writeCallback($connection, $string) - { - $this->content .= $string; - - if (!$this->mime) { - $this->mime = finfo_buffer($this->finfo, $this->content); - - if (!in_array($this->mime, static::$mimetypes, true)) { - $this->mime = null; - - return -1; - } - } - - if (!($info = getimagesizefromstring($this->content))) { - return strlen($string); - } - - $this->info = [ - 'width' => $info[0], - 'height' => $info[1], - 'size' => $info[0] * $info[1], - 'mime' => $this->mime, - ]; - - return -1; - } -} diff --git a/src/ImageInfo/Guzzle5.php b/src/ImageInfo/Guzzle5.php deleted file mode 100644 index 4cbd11d8..00000000 --- a/src/ImageInfo/Guzzle5.php +++ /dev/null @@ -1,74 +0,0 @@ - false, - 'timeout' => 10, - 'connect_timeout' => 20, - 'headers' => [ - 'User-Agent' => 'Embed PHP Library', - ], - 'allow_redirects' => [ - 'max' => 20, - 'referer' => true, - ], - ]; - - /** - * {@inheritdoc} - */ - public static function getImagesInfo(array $urls, array $config = null) - { - $client = isset($config['client']) ? $config['client'] : new Client([ - 'defaults' => static::$config, - ]); - - $result = []; - - // Build parallel requests - $requests = []; - foreach ($urls as $url) { - if (strpos($url['value'], 'data:') === 0) { - if ($info = static::getEmbeddedImageInfo($url['value'])) { - $result[] = array_merge($url, $info); - } - continue; - } - - $requests[] = $client->createRequest('GET', $url['value']); - } - - // Execute in parallel - $responses = Pool::batch($client, $requests); - - // Build result set - foreach ($responses as $i => $response) { - if ($response instanceof RequestException) { - continue; - } - - if (($size = getimagesizefromstring($response->getBody())) !== false) { - $result[] = [ - 'width' => $size[0], - 'height' => $size[1], - 'size' => $size[0] * $size[1], - 'mime' => $size['mime'], - ] + $urls[$i]; - } - } - - return $result; - } -} diff --git a/src/ImageInfo/ImageInfoInterface.php b/src/ImageInfo/ImageInfoInterface.php deleted file mode 100644 index c3cf155f..00000000 --- a/src/ImageInfo/ImageInfoInterface.php +++ /dev/null @@ -1,19 +0,0 @@ - $info[0], - 'height' => $info[1], - 'size' => $info[0] * $info[1], - 'mime' => $info['mime'], - ]; - } - - return false; - } -} diff --git a/src/LinkedData.php b/src/LinkedData.php new file mode 100644 index 00000000..91876654 --- /dev/null +++ b/src/LinkedData.php @@ -0,0 +1,193 @@ + */ + private array $allData = []; + + /** + * @return mixed + */ + public function get(string ...$keys) + { + $graph = $this->getGraph(); + + if ($graph === null) { + return null; + } + + foreach ($keys as $key) { + $subkeys = explode('.', $key); + + foreach ($graph->getNodes() as $node) { + $value = self::getValue($node, ...$subkeys); + + if ($value !== null && $value !== '' && $value !== false && $value !== []) { + return $value; + } + } + } + + return null; + } + + /** + * @return array + */ + public function getAll(): array + { + if ($this->allData === []) { + $this->fetchData(); + } + + return $this->allData; + } + + private function getGraph(?string $name = null): ?GraphInterface + { + if (!isset($this->document)) { + try { + $encoded = json_encode($this->all()); + if ($encoded === false) { + $encoded = '{}'; + } + $this->document = LdDocument::load($encoded); + } catch (Throwable $throwable) { + $this->document = LdDocument::load('{}'); + return null; + } + } + + return $this->document->getGraph($name); + } + + /** + * @return array + */ + protected function fetchData(): array + { + $this->allData = []; + + $document = $this->extractor->getDocument(); + $nodes = $document->select('.//script', ['type' => 'application/ld+json'])->strAll(); + + if ($nodes === []) { + return []; + } + + try { + /** @var array $data */ + $data = []; + $request_uri = (string)$this->extractor->getUri(); + foreach ($nodes as $node) { + $ldjson = json_decode($node, true); + if (is_array($ldjson) && $ldjson !== []) { + + // some pages with multiple ld+json blocks will put + // each block into an array (Flickr does this). Most + // appear to put an object in each ld+json block. To + // prevent them from stepping on one another, the ones + // that are not arrays will be put into an array. + if (!array_is_list($ldjson)) { + $ldjson = [$ldjson]; + } + + foreach ($ldjson as $ldNode) { + if (!is_array($ldNode)) { + continue; + } + if ($data === []) { + /** @var array $data */ + $data = $ldNode; + } elseif (isset($ldNode['mainEntityOfPage'])) { + $url = ''; + if (is_string($ldNode['mainEntityOfPage'])) { + $url = $ldNode['mainEntityOfPage']; + } elseif (is_array($ldNode['mainEntityOfPage']) && isset($ldNode['mainEntityOfPage']['@id']) && is_string($ldNode['mainEntityOfPage']['@id'])) { + $url = $ldNode['mainEntityOfPage']['@id']; + } + if ($url !== '' && $url === $request_uri) { + /** @var array $data */ + $data = $ldNode; + } + } + } + + /** @var array $mergedData */ + $mergedData = array_merge($this->allData, $ldjson); + $this->allData = $mergedData; + } + } + + return $data; + } catch (Exception $exception) { + return []; + } + } + + /** + * @return mixed + */ + private static function getValue(Node $node, string ...$keys) + { + foreach ($keys as $key) { + if (is_array($node)) { + $node = array_shift($node); + } + if (!$node instanceof Node) { + return null; + } + + $node = $node->getProperty("http://schema.org/%7B$key%7D"); + + if ($node === null) { + return null; + } + } + + return self::detectValue($node); + } + + /** + * @param mixed $value + * @return mixed + */ + private static function detectValue($value) + { + if (is_array($value)) { + return array_map( + fn ($val) => self::detectValue($val), + array_values($value) + ); + } + + if (is_scalar($value)) { + return $value; + } + + if ($value instanceof Node) { + return $value->getId(); + } + + if (is_object($value) && method_exists($value, 'getValue')) { + return $value->getValue(); + } + + return null; + } +} diff --git a/src/Metas.php b/src/Metas.php new file mode 100644 index 00000000..0450370f --- /dev/null +++ b/src/Metas.php @@ -0,0 +1,58 @@ + + */ + protected function fetchData(): array + { + $data = []; + $document = $this->extractor->getDocument(); + + foreach ($document->select('.//meta')->nodes() as $node) { + if (!($node instanceof \DOMElement)) { + continue; + } + $type = $node->getAttribute('name'); + if ($type === '') { + $type = $node->getAttribute('property'); + } + if ($type === '') { + $type = $node->getAttribute('itemprop'); + } + $value = $node->getAttribute('content'); + + if ($value !== '' && $type !== '') { + $type = strtolower($type); + $data[$type] ??= []; + $data[$type][] = $value; + } + } + + return $data; + } + + /** + * @return mixed + */ + public function get(string ...$keys) + { + $data = $this->all(); + + foreach ($keys as $key) { + $values = $data[$key] ?? null; + + if ($values !== null && $values !== '' && $values !== []) { + return $values; + } + } + + return null; + } +} diff --git a/src/OEmbed.php b/src/OEmbed.php new file mode 100644 index 00000000..b530591f --- /dev/null +++ b/src/OEmbed.php @@ -0,0 +1,232 @@ +|null */ + private static $providers = null; + + /** @var array */ + private array $defaults = []; + + /** + * @return array + */ + private static function getProviders(): array + { + if (self::$providers === null) { + /** @var array $loaded */ + $loaded = require __DIR__.'/resources/oembed.php'; + self::$providers = $loaded; + } + + return self::$providers; + } + + /** + * @return array + */ + public function getOembedQueryParameters(string $url): array + { + $queryParameters = ['url' => $url, 'format' => 'json']; + $setting = $this->extractor->getSetting('oembed:query_parameters'); + $additional = is_array($setting) ? $setting : []; + + /** @var array $result */ + $result = array_merge($queryParameters, $additional); + return $result; + } + + /** + * @return array + */ + protected function fetchData(): array + { + $this->endpoint = $this->detectEndpoint(); + + if ($this->endpoint === null) { + return []; + } + + $crawler = $this->extractor->getCrawler(); + $request = $crawler->createRequest('GET', $this->endpoint); + $response = $crawler->sendRequest($request); + + if (self::isXML($request->getUri())) { + return $this->extractXML((string) $response->getBody()); + } + + return $this->extractJSON((string) $response->getBody()); + } + + protected function detectEndpoint(): ?UriInterface + { + $document = $this->extractor->getDocument(); + + $endpoint = null; + $types = [ + 'application/json+oembed', + 'text/json+oembed', + 'application/xml+oembed', + 'text/xml+oembed', + ]; + + foreach ($types as $type) { + $endpoint = $document->link('alternate', ['type' => $type]); + if ($endpoint !== null) { + break; + } + } + + if ($endpoint === null) { + return $this->detectEndpointFromProviders(); + } + + // Add configured OEmbed query parameters + parse_str($endpoint->getQuery(), $query); + $setting = $this->extractor->getSetting('oembed:query_parameters'); + $additional = is_array($setting) ? $setting : []; + $query = array_merge($query, $additional); + $endpoint = $endpoint->withQuery(http_build_query($query)); + + return $endpoint; + } + + private function detectEndpointFromProviders(): ?UriInterface + { + $url = (string) $this->extractor->getUri(); + + $endpoint = $this->detectEndpointFromUrl($url); + if ($endpoint !== null) { + return $endpoint; + } + + $initialUrl = (string) $this->extractor->getRequest()->getUri(); + + if ($initialUrl !== $url) { + $endpoint = $this->detectEndpointFromUrl($initialUrl); + if ($endpoint !== null) { + $this->defaults['url'] = $initialUrl; + return $endpoint; + } + } + + return null; + } + + private function detectEndpointFromUrl(string $url): ?UriInterface + { + $endpoint = self::searchEndpoint(self::getProviders(), $url); + + if ($endpoint === null || $endpoint === '') { + return null; + } + + return $this->extractor->getCrawler() + ->createUri($endpoint) + ->withQuery(http_build_query($this->getOembedQueryParameters($url))); + } + + /** + * @param array $providers + */ + private static function searchEndpoint(array $providers, string $url): ?string + { + foreach ($providers as $endpoint => $patterns) { + if (!is_array($patterns)) { + continue; + } + foreach ($patterns as $pattern) { + if (!is_string($pattern)) { + continue; + } + $matchResult = preg_match($pattern, $url); + if ($matchResult === 1) { + return is_string($endpoint) ? $endpoint : null; + } + } + } + + return null; + } + + private static function isXML(UriInterface $uri): bool + { + $extension = pathinfo($uri->getPath(), PATHINFO_EXTENSION); + + if (strtolower($extension) === 'xml') { + return true; + } + + parse_str($uri->getQuery(), $params); + $format = $params['format'] ?? null; + + if (is_string($format) && $format !== '' && strtolower($format) === 'xml') { + return true; + } + + return false; + } + + /** + * @return array + */ + private function extractXML(string $xml): array + { + try { + // Remove the DOCTYPE declaration for to prevent XML Quadratic Blowup vulnerability + $cleanedXml = preg_replace('/^]*+>/i', '', $xml, 1); + if (!is_string($cleanedXml)) { + return []; + } + $data = []; + $errors = libxml_use_internal_errors(true); + $content = new SimpleXMLElement($cleanedXml); + libxml_use_internal_errors($errors); + + foreach ($content as $element) { + $value = trim((string) $element); + + if (stripos($value, 'getName(); + $data[$name] = $value; + } + + return $data !== [] ? ($data + $this->defaults) : []; + } catch (Exception $exception) { + return []; + } + } + + /** + * @return array + */ + private function extractJSON(string $json): array + { + try { + /** @var mixed $decoded */ + $decoded = json_decode($json, true); + + if (!is_array($decoded)) { + return []; + } + + /** @var array $result */ + $result = $decoded + $this->defaults; + return $result; + } catch (Exception $exception) { + return []; + } + } +} diff --git a/src/Providers/Api/Archive.php b/src/Providers/Api/Archive.php deleted file mode 100644 index 78713b94..00000000 --- a/src/Providers/Api/Archive.php +++ /dev/null @@ -1,95 +0,0 @@ -request->withQueryParameter('output', 'json'); - - if (($json = $api->getJsonContent())) { - $this->bag->set($json); - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('metadata[title][0]'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('metadata[description][0]'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - switch ($this->bag->get('metadata[mediatype][0]')) { - case 'movies': - return 'video'; - - case 'audio': - return 'audio'; - - case 'texts': - return 'rich'; - } - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return 'Internet Archive'; - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->bag->get('url'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - $this->bag->get('metadata[creator][0]'); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = (array) $this->bag->get('misc[image]'); - - foreach (array_keys((array) $this->bag->get('files')) as $url) { - $images[] = $url; - } - - return $images; - } -} diff --git a/src/Providers/Api/Facebook.php b/src/Providers/Api/Facebook.php deleted file mode 100644 index 0db283ee..00000000 --- a/src/Providers/Api/Facebook.php +++ /dev/null @@ -1,189 +0,0 @@ - null, - ]; - - private $isEmbeddable = false; - - /** - * {@inheritdoc} - */ - public function run() - { - if (($id = $this->getId($this->request))) { - if ($this->config['key']) { - $api = $this->request - ->withUrl('https://graph.facebook.com/'.$id) - ->withQueryParameter('access_token', $this->config['key']); - - if ($json = $api->getJsonContent()) { - $this->bag->set($json); - } - } - - $this->bag->set('id', $id); - } - } - - /** - * Returns the id found in a facebook url. - * - * @param Url $url - * - * @return string - */ - private function getId(Url $url) - { - if ($url->hasQueryParameter('story_fbid')) { - $this->isEmbeddable = true; - - return $url->getQueryParameter('story_fbid'); - } - - if ($url->hasQueryParameter('fbid')) { - return $url->getQueryParameter('fbid'); - } - - if ($url->hasQueryParameter('id')) { - return $url->getQueryParameter('id'); - } - - if ($url->getDirectoryPosition(0) === 'events') { - $this->isEmbeddable = true; - - return $url->getDirectoryPosition(1); - } - - if ($url->getDirectoryPosition(0) === 'pages') { - return $url->getDirectoryPosition(2); - } - - if ($url->getDirectoryPosition(1) === 'posts') { - $this->isEmbeddable = true; - - return $url->getDirectoryPosition(2); - } - - if ($url->getDirectoryPosition(2) === 'posts') { - $this->isEmbeddable = true; - - return $url->getDirectoryPosition(3); - } - - return $url->getDirectoryPosition(0); - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('name'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description') ?: $this->bag->get('about'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - if ($this->isEmbeddable) { - return 'rich'; - } - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->bag->get('url'); - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if ($this->isEmbeddable) { - $url = $this->getUrl() ?: $this->request->getUrl(); - $width = $this->getWidth(); - - return << - - -
-EOT; - } - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - if ($this->isEmbeddable) { - return 500; - } - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return 'Facebook'; - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('username'); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = []; - - if (($cover = $this->bag->get('cover[source]'))) { - $images[] = $cover; - } - - if (($id = $this->bag->get('id'))) { - $images[] = 'https://graph.facebook.com/'.$id.'/picture'; - } - - return $images; - } -} diff --git a/src/Providers/Api/Gist.php b/src/Providers/Api/Gist.php deleted file mode 100644 index 92366241..00000000 --- a/src/Providers/Api/Gist.php +++ /dev/null @@ -1,44 +0,0 @@ -request->withExtension('json'); - - if (($json = $api->getJsonContent())) { - $this->bag->set($json); - } - } - - /** - * {@inheritdoc} - */ - public function getType() - { - if ($this->getCode() !== null) { - return 'rich'; - } - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if (($code = $this->bag->get('div')) && ($stylesheet = $this->bag->get('stylesheet'))) { - return ''.$code; - } - } -} diff --git a/src/Providers/Api/GoogleMaps.php b/src/Providers/Api/GoogleMaps.php deleted file mode 100644 index 1e9c0aa4..00000000 --- a/src/Providers/Api/GoogleMaps.php +++ /dev/null @@ -1,80 +0,0 @@ - null, - ]; - - /** - * {@inheritdoc} - */ - public function run() - { - $mode = $this->request->getDirectoryPosition(1); - - switch ($mode) { - case 'place': - case 'dir': - case 'search': - $this->mode = $mode; - break; - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - if ($this->mode === 'place') { - return $this->request->getDirectoryPosition(2); - } - - if ($this->mode === 'dir') { - return $this->request->getDirectoryPosition(2).' / '.$this->request->getDirectoryPosition(3); - } - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if (empty($this->config['key'])) { - return; - } - - switch ($this->mode) { - case 'place': - case 'search': - return Utils::iframe($this->request->createUrl() - ->withPath('maps/embed/v1/'.$this->mode) - ->withQueryParameters([ - 'q' => $this->request->getDirectoryPosition(2), - 'key' => $this->config['key'], - ]) - ); - - case 'dir': - return Utils::iframe($this->request->createUrl() - ->withPath('maps/embed/v1/directions') - ->withQueryParameters([ - 'origin' => $this->request->getDirectoryPosition(2), - 'destination' => $this->request->getDirectoryPosition(3), - 'key' => $this->config['key'], - ]) - ); - } - } -} diff --git a/src/Providers/Api/Imageshack.php b/src/Providers/Api/Imageshack.php deleted file mode 100644 index d2bcf922..00000000 --- a/src/Providers/Api/Imageshack.php +++ /dev/null @@ -1,101 +0,0 @@ -request->getDirectoryPosition(1); - $api = $this->request->withUrl('https://api.imageshack.com/v2/images/'.$id); - - if (($json = $api->getJsonContent()) && !empty($json['result'])) { - $this->bag->set($json['result']); - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return 'photo'; - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - return $this->bag->get('creation_date'); - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return $this->bag->get('width'); - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return $this->bag->get('height'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('owner[username]'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorUrl() - { - $username = $this->getAuthorName(); - - if (!empty($username)) { - return 'http://imageshack.com/user/'.$username; - } - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - return (array) $this->bag->get('direct_link'); - } -} diff --git a/src/Providers/Api/Soundcloud.php b/src/Providers/Api/Soundcloud.php deleted file mode 100644 index ab3c0fa3..00000000 --- a/src/Providers/Api/Soundcloud.php +++ /dev/null @@ -1,87 +0,0 @@ - null, - ]; - - /** - * {@inheritdoc} - */ - public function run() - { - if (!empty($this->config['key'])) { - $api = $this->request - ->withUrl('http://api.soundcloud.com/resolve.json') - ->withQueryParameter('client_id', $this->config['key']) - ->withQueryParameter('url', $this->request->getUrl()); - - if ($json = $api->getJsonContent()) { - $this->bag->set($json); - } - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->bag->get('permalink_url'); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = []; - - if (!$this->bag->get('artwork_url') && ($img = $this->bag->get('user[avatar_url]'))) { - $images[] = str_replace('-large.jpg', '-t500x500.jpg', $img); - } - - return $images; - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('user[username]'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorUrl() - { - return $this->bag->get('user[permalink_url]'); - } -} diff --git a/src/Providers/Api/Wikipedia.php b/src/Providers/Api/Wikipedia.php deleted file mode 100644 index 21d9b9af..00000000 --- a/src/Providers/Api/Wikipedia.php +++ /dev/null @@ -1,128 +0,0 @@ -request->getDirectoryPosition(1); - - if (!empty($titles)) { - //extract images - $api = $this->request - ->withPath('/w/api.php') - ->withQueryParameters([ - 'action' => 'query', - 'format' => 'json', - 'continue' => '', - 'titles' => $titles, - 'prop' => 'images', - ]); - - if (($json = $api->getJsonContent())) { - $this->bag->set('images', $json); - } - - //extract content - $api = $api - ->withQueryParameter('prop', 'extracts') - ->withQueryParameter('exchars', 1500); - - if (($json = $api->getJsonContent())) { - $this->bag->set('extracts', $json); - } - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - $pages = $this->bag->get('extracts[query][pages]'); - - if ($pages) { - $page = current($pages); - - return strip_tags($page['title']); - } - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - $pages = $this->bag->get('extracts[query][pages]'); - - if ($pages) { - $page = current($pages); - - return isset($page['extract']) ? strip_tags($page['extract']) : null; - } - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = []; - - $pages = $this->bag->get('images[query][pages]'); - - if ($pages) { - $page = current($pages); - - $imgs = []; - - if (isset($page['images'])) { - foreach ($page['images'] as $image) { - switch (strrchr($image['title'], '.')) { - case '.png': - case '.jpg': - case '.gif': - case '.jpeg': - $imgs[] = $image['title']; - break; - } - } - } - - //Get image urls - if ($imgs) { - $json = $this->request - ->withPath('/w/api.php') - ->withQueryParameters([ - 'action' => 'query', - 'prop' => 'imageinfo', - 'iiprop' => 'url', - 'format' => 'json', - 'continue' => '', - 'titles' => implode('|', $imgs), - ]) - ->getJsonContent(); - - if (isset($json['query']['pages'])) { - foreach ($json['query']['pages'] as $page) { - if (isset($page['imageinfo'][0]['url'])) { - $images[] = $page['imageinfo'][0]['url']; - } - } - } - } - } - - return $images; - } -} diff --git a/src/Providers/Dcterms.php b/src/Providers/Dcterms.php deleted file mode 100644 index eec27925..00000000 --- a/src/Providers/Dcterms.php +++ /dev/null @@ -1,68 +0,0 @@ -request->getHtmlContent())) { - return false; - } - - foreach (Utils::getMetas($html) as $meta) { - foreach (['dc.', 'dc:', 'dcterms:'] as $prefix) { - if (stripos($meta[0], $prefix) === 0) { - $key = substr($meta[0], strlen($prefix)); - $this->bag->set($key, $meta[1]); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('author'); - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - foreach (['date', 'date.created', 'date.issued'] as $key) { - if ($found = $this->bag->get($key)) { - return $found; - } - } - } -} diff --git a/src/Providers/Html.php b/src/Providers/Html.php deleted file mode 100644 index 3125be8e..00000000 --- a/src/Providers/Html.php +++ /dev/null @@ -1,357 +0,0 @@ - -1, - ]; - - /** - * {@inheritdoc} - */ - public function run() - { - if (!($html = $this->request->getHtmlContent())) { - return false; - } - - self::extractFromLink($html, $this->bag); - self::extractFromMeta($html, $this->bag); - - $main = self::getMainElement($html); - - self::extractImages($main, $this->bag, $this->request->getDomain()); - - //Title - $title = $html->getElementsByTagName('title'); - - if ($title->length) { - $this->bag->set('title', $title->item(0)->nodeValue); - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - return $this->bag->has('video_src') ? 'video' : null; - } - - /** - * {@inheritdoc} - */ - public function getTags() - { - if (!$this->bag->has('keywords')) { - return []; - } - - $keywords = $this->bag->get('keywords'); - - //some sites, contains the keywords separated by commas - if (strpos($keywords, ',')) { - $keywords = explode(',', $keywords); - //and others by spaces (ex: youtube) - } else { - $keywords = explode(' ', $keywords); - } - - return array_filter(array_map('trim', $keywords)); - } - - /** - * {@inheritdoc} - */ - public function getSource() - { - $feeds = $this->bag->get('feeds'); - - return isset($feeds[0]) ? $feeds[0] : null; - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if ($this->bag->has('video_src')) { - switch ($this->bag->get('video_type')) { - case 'application/x-shockwave-flash': - return Utils::flash($this->bag->get('video_src'), $this->getWidth(), $this->getHeight()); - } - } - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->bag->get('canonical'); - } - - /** - * {@inheritdoc} - */ - public function getProviderIconsUrls() - { - return (array) $this->bag->get('icons') ?: []; - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = (array) $this->bag->get('images'); - - if ($this->config['maxImages'] > -1) { - return array_slice($images, 0, $this->config['maxImages']); - } - - return $images; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return (integer) $this->bag->get('video_width') ?: null; - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return (integer) $this->bag->get('video_height') ?: null; - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - $keys = [ - 'article:published_time', - 'created', - 'date', - 'datepublished', - 'datePublished', - 'newsrepublic:publish_date', - 'pagerender', - 'pub_date', - 'publication-date', - 'publish-date', - 'rc.datecreation', - 'timestamp', - 'article:modified_time', - 'eomportal-lastupdate', - 'shareaholic:article_published_time', - ]; - - foreach ($keys as $key) { - if ($found = $this->bag->get($key)) { - return $found; - } - } - } - - /** - * Extract information from the elements. - * - * @param \DOMDocument $html - * @param Bag $bag - */ - protected static function extractFromLink(\DOMDocument $html, Bag $bag) - { - foreach (Utils::getLinks($html) as $link) { - list($rel, $href, $element) = $link; - - if (empty($href)) { - continue; - } - - switch ($rel) { - case 'favicon': - case 'favico': - case 'icon': - case 'shortcut icon': - case 'apple-touch-icon-precomposed': - case 'apple-touch-icon': - $bag->add('icons', $href); - break; - - case 'image_src': - $bag->add('images', $href); - break; - - case 'alternate': - switch ($element->getAttribute('type')) { - case 'application/rss+xml': - case 'application/atom+xml': - $bag->add('feeds', $href); - break; - } - break; - - default: - $bag->set($rel, $href); - } - } - } - - /** - * Extract information from the elements. - * - * @param \DOMDocument $html - * @param Bag $bag - */ - protected static function extractFromMeta(\DOMDocument $html, Bag $bag) - { - foreach (Utils::getMetas($html) as $meta) { - list($name, $value, $element) = $meta; - - if (!$value) { - continue; - } - - if ($name) { - $name = strtolower($name); - - switch ($name) { - case 'msapplication-tileimage': - $bag->add('icons', $value); - continue 2; - - default: - $bag->set($name, $value); - continue 2; - } - } - - if ($element->hasAttribute('itemprop')) { - $bag->set($element->getAttribute('itemprop'), $value); - } - - if ($element->hasAttribute('http-equiv')) { - $bag->set($element->getAttribute('http-equiv'), $value); - } - } - } - - /** - * Extract elements. - * - * @param \DOMElement $html - * @param Bag $bag - * @param null|string $domain - */ - protected static function extractImages(\DOMElement $html, Bag $bag, $domain = null) - { - foreach ($html->getElementsByTagName('img') as $img) { - if ($img->hasAttribute('src')) { - $src = new Url($img->getAttribute('src')); - - //Is src relative? - if (!$src->getDomain()) { - $bag->add('images', $src->getUrl()); - continue; - } - - //Avoid external images or in external links - if ($domain !== null) { - if ($src->getDomain() !== $domain) { - continue; - } - - $parent = $img->parentNode; - - while ($parent && isset($parent->tagName)) { - if ($parent->tagName === 'a') { - if ($parent->hasAttribute('href')) { - $href = new Url($parent->getAttribute('href')); - - if ($href->getDomain() && $src->getDomain() !== $domain) { - continue 2; - } - } - if ($parent->hasAttribute('rel') && (string) $parent->getAttribute('rel') === 'nofollow') { - continue 2; - } - - break; - } - - $parent = $parent->parentNode; - } - - $bag->add('images', $src->getUrl()); - } - } - } - } - - /** - * Returns the main element of the document. - * - * @param \DOMDocument $html - * - * @return \DOMElement - */ - protected static function getMainElement(\DOMDocument $html) - { - //
- $content = $html->getElementsByTagName('main'); - - if ($content->length !== 0) { - return $content->item(0); - } - - // Popular ids: #main, #content, #page - $content = $html->getElementById('main') ?: $html->getElementById('content') ?: $html->getElementById('page'); - - if ($content) { - return $content; - } - - // Wordpress ids: #post-* - foreach ($html->getElementsByTagName('article') as $article) { - if ($article->hasAttribute('id') && (strpos($article->getAttribute('id'), 'post-') === 0)) { - return $article; - } - } - - // Returns or - return $html->getElementsByTagName('body')->item(0) ?: $html->getElementsByTagName('html')->item(0); - } -} diff --git a/src/Providers/OEmbed.php b/src/Providers/OEmbed.php deleted file mode 100644 index 50768692..00000000 --- a/src/Providers/OEmbed.php +++ /dev/null @@ -1,307 +0,0 @@ - [], - 'embedlyKey' => null, - 'iframelyKey' => null, - ]; - - /** - * {@inheritdoc} - */ - public function run() - { - $endPoint = null; - $params = $this->config['parameters']; - - if (self::providerEmbedInDomIsBroken($this->request) || (!($html = $this->request->getHtmlContent()) || !($endPoint = self::getEndPointFromDom($html)))) { - if (($info = self::getEndPointFromRequest($this->request, $this->config))) { - $endPoint = $info['endPoint']; - $params += $info['params']; - } - } - - if (!$endPoint) { - return; - } - - $endPointRequest = $this->request - ->withUrl($endPoint) - ->withAddedQueryParameters($params); - - if (!$endPointRequest->hasQueryParameter('url')) { - $endPointRequest = $endPointRequest->withQueryParameter('url', $this->request->getUrl()); - } - - // extract from xml - if (($endPointRequest->getExtension() === 'xml') || ($endPointRequest->getQueryParameter('format') === 'xml')) { - if ($parameters = $endPointRequest->getXmlContent()) { - foreach ($parameters as $element) { - $this->bag->set($element->getName(), (string) $element); - } - } - // extract from json - } else { - $endPointRequest = $endPointRequest->withQueryParameter('format', 'json'); - - if (($parameters = $endPointRequest->getJsonContent()) && empty($parameters['Error'])) { - $this->bag->set($parameters); - } - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - $type = $this->bag->get('type'); - - if (strpos($type, ':') !== false) { - $type = substr(strrchr($type, ':'), 1); - } - - switch ($type) { - case 'video': - case 'photo': - case 'link': - case 'rich': - return $type; - - case 'movie': - return 'video'; - } - } - - /** - * {@inheritdoc} - */ - public function getTags() - { - if ($this->bag->has('meta[keywords]')) { - //it means we are using iframe.ly api - return array_map('trim', explode(',', $this->bag->get('meta[keywords]'))); - } - - return []; - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - return $this->bag->get('html'); - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - if ($this->getType() === 'photo') { - return $this->bag->get('web_page'); - } - - return $this->bag->get('url') ?: $this->bag->get('web_page'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('author_name'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorUrl() - { - return $this->bag->get('author_url'); - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return $this->bag->get('provider_name'); - } - - /** - * {@inheritdoc} - */ - public function getProviderUrl() - { - return $this->bag->get('provider_url'); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = []; - - if ($this->getType() === 'photo') { - $images[] = $this->bag->get('url'); - } - - if ($this->bag->has('image')) { - $images[] = $this->bag->get('image'); - } - - if ($this->bag->has('thumbnail')) { - $images[] = $this->bag->get('thumbnail'); - } - - if ($this->bag->has('thumbnail_url')) { - $images[] = $this->bag->get('thumbnail_url'); - } - - return $images; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return $this->bag->get('width'); - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return $this->bag->get('height'); - } - - /** - * Extract oembed information from the elements - * Note: Some sites use instead. - * - * @param \DOMDocument $html - * - * @return string|null - */ - protected static function getEndPointFromDom(\DOMDocument $html) - { - foreach (['link', 'meta'] as $tagName) { - foreach (Utils::getLinks($html, $tagName) as $link) { - list($rel, $href, $element) = $link; - - if (empty($href)) { - continue; - } - - if ($rel === 'alternate') { - switch (strtolower($element->getAttribute('type'))) { - case 'application/json+oembed': - case 'application/xml+oembed': - case 'text/json+oembed': - case 'text/xml+oembed': - return $href; - } - } - } - } - } - - /** - * Returns the oembed link from the request. - * - * @param Request $request - * @param array $config - * - * @return array|null - */ - protected static function getEndPointFromRequest(Request $request, array $config) - { - //Search the oembed provider using the domain - $class = self::getClassFromRequest($request); - - if (class_exists($class) && $request->match($class::getPatterns())) { - return [ - 'endPoint' => $class::getEndpoint($request), - 'params' => $class::getParams($request), - ]; - } - - //Search using embedly - if (!empty($config['embedlyKey']) && $request->match(OEmbed\Embedly::getPatterns())) { - return [ - 'endPoint' => OEmbed\Embedly::getEndpoint($request), - 'params' => OEmbed\Embedly::getParams($request) + ['key' => $config['embedlyKey']], - ]; - } - - //Search using iframely - if (!empty($config['iframelyKey']) && $request->match(OEmbed\Iframely::getPatterns())) { - return [ - 'endPoint' => OEmbed\Iframely::getEndpoint($request), - 'params' => OEmbed\Iframely::getParams($request) + ['api_key' => $config['iframelyKey']], - ]; - } - } - - /** - * Return the class name implementing an oEmbed provider. - * - * @param Request $request - * - * @return string - */ - protected static function getClassFromRequest(Request $request) - { - return 'Embed\\Providers\\OEmbed\\'.$request->getClassNameForDomain(); - } - - /** - * @param Request $request - * - * @return bool - */ - protected static function providerEmbedInDomIsBroken(Request $request) - { - $class = self::getClassFromRequest($request); - - if (class_exists($class) && $request->match($class::getPatterns())) { - return $class::embedInDomIsBroken(); - } - - // Fall-through default in case this called for an invalid class - return false; - } -} diff --git a/src/Providers/OEmbed/Bambuser.php b/src/Providers/OEmbed/Bambuser.php deleted file mode 100644 index e39a99e5..00000000 --- a/src/Providers/OEmbed/Bambuser.php +++ /dev/null @@ -1,24 +0,0 @@ - 'embed', - ]; - } -} diff --git a/src/Providers/OEmbed/Dotsub.php b/src/Providers/OEmbed/Dotsub.php deleted file mode 100644 index 217b637f..00000000 --- a/src/Providers/OEmbed/Dotsub.php +++ /dev/null @@ -1,24 +0,0 @@ - $url->withScheme('http')->getUrl()]; - } -} diff --git a/src/Providers/OEmbed/Kickstarter.php b/src/Providers/OEmbed/Kickstarter.php deleted file mode 100644 index e03bd65e..00000000 --- a/src/Providers/OEmbed/Kickstarter.php +++ /dev/null @@ -1,24 +0,0 @@ -request->getHtmlContent())) { - return false; - } - - foreach (Utils::getMetas($html) as $meta) { - list($name, $value) = $meta; - - if (strpos($name, 'og:article:') === 0) { - $name = substr($name, 11); - } elseif (strpos($name, 'og:') === 0) { - $name = substr($name, 3); - } else { - continue; - } - - if ($name === 'image') { - $this->bag->add('images', $value); - } elseif (strpos($name, ':tag') !== false) { - $this->bag->add('tags', $value); - } else { - $this->bag->set($name, $value); - } - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - $type = $this->bag->get('type'); - - if (strpos($type, ':') !== false) { - $type = substr(strrchr($type, ':'), 1); - } - - switch ($type) { - case 'video': - case 'photo': - case 'link': - case 'rich': - return $type; - - case 'article': - return 'link'; - } - - if ($this->bag->has('video')) { - return 'video'; - } - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if ($this->bag->has('video')) { - $video = $this->bag->get('video'); - - if (!($videoPath = parse_url(http://github.com/$video,%20PHP_URL_PATH)) || !($type = pathinfo($videoPath, PATHINFO_EXTENSION))) { - $type = $this->bag->get('video:type'); - } - - switch ($type) { - case 'swf': - case 'application/x-shockwave-flash': - return Utils::flash($video, $this->getWidth(), $this->getHeight()); - - case 'mp4': - case 'ogg': - case 'ogv': - case 'webm': - case 'application/mp4': - case 'video/mp4': - case 'video/ogg': - case 'video/ogv': - case 'video/webm': - $images = $this->getImagesUrls(); - - return Utils::videoHtml(current($images), $video, $this->getWidth(), $this->getHeight()); - - case 'text/html': - return Utils::iframe($video, $this->getWidth(), $this->getHeight()); - } - } - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->bag->get('url'); - } - - /** - * {@inheritdoc} - */ - public function getTags() - { - return (array) $this->bag->get('tags') ?: []; - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - return $this->bag->get('site_name'); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - return (array) $this->bag->get('images') ?: []; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return $this->bag->get('image:width') ?: $this->bag->get('video:width'); - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return $this->bag->get('image:height') ?: $this->bag->get('video:height'); - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - return $this->bag->get('published_time') ?: $this->bag->get('updated_time'); - } -} diff --git a/src/Providers/Provider.php b/src/Providers/Provider.php deleted file mode 100644 index 2137031c..00000000 --- a/src/Providers/Provider.php +++ /dev/null @@ -1,144 +0,0 @@ -bag = new Bag(); - $this->request = $request; - - if ($config) { - $this->config = array_replace($this->config, $config); - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - } - - /** - * {@inheritdoc} - */ - public function getType() - { - } - - /** - * {@inheritdoc} - */ - public function getTags() - { - return []; - } - /** - * {@inheritdoc} - */ - public function getSource() - { - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - } - - /** - * {@inheritdoc} - */ - public function getAuthorUrl() - { - } - - /** - * {@inheritdoc} - */ - public function getProviderIconsUrls() - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getProviderName() - { - } - - /** - * {@inheritdoc} - */ - public function getProviderUrl() - { - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - return []; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - } -} diff --git a/src/Providers/ProviderInterface.php b/src/Providers/ProviderInterface.php deleted file mode 100644 index d7123332..00000000 --- a/src/Providers/ProviderInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -request->getHtmlContent())) { - return false; - } - - foreach (Utils::getMetas($html) as $meta) { - list($name, $value) = $meta; - - if (strpos($name, 'sailthru.') === 0) { - $this->bag->set(substr($name, 9), $value); - } - } - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - $images = []; - - foreach ($this->bag->getAll() as $name => $value) { - if (strpos($name, 'image') !== false) { - $images[] = $value; - } - } - - return $images; - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('author'); - } - - /** - * {@inheritdoc} - */ - public function getPublishedTime() - { - return $this->bag->get('date'); - } -} diff --git a/src/Providers/TwitterCards.php b/src/Providers/TwitterCards.php deleted file mode 100644 index 5ef4ebec..00000000 --- a/src/Providers/TwitterCards.php +++ /dev/null @@ -1,126 +0,0 @@ -request->getHtmlContent())) { - return false; - } - - foreach (Utils::getMetas($html) as $meta) { - list($name, $value) = $meta; - - if (strpos($name, 'twitter:') === 0) { - $name = substr($name, 8); - - if ($name === 'image') { - $this->bag->add('images', $value); - } else { - $this->bag->set($name, $value); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function getTitle() - { - return $this->bag->get('title'); - } - - /** - * {@inheritdoc} - */ - public function getDescription() - { - return $this->bag->get('description'); - } - - /** - * {@inheritdoc} - */ - public function getType() - { - $type = $this->bag->get('card'); - - if (strpos($type, ':') !== false) { - $type = substr(strrchr($type, ':'), 1); - } - - switch ($type) { - case 'video': - case 'photo': - case 'link': - case 'rich': - return $type; - - case 'player': - return 'video'; - } - } - - /** - * {@inheritdoc} - */ - public function getCode() - { - if ($this->bag->has('player')) { - return Utils::iframe($this->bag->get('player'), $this->getWidth(), $this->getHeight()); - } - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->bag->get('url'); - } - - /** - * {@inheritdoc} - */ - public function getAuthorName() - { - return $this->bag->get('creator'); - } - - /** - * {@inheritdoc} - */ - public function getImagesUrls() - { - return (array) $this->bag->get('images') ?: []; - } - - /** - * {@inheritdoc} - */ - public function getWidth() - { - return $this->bag->get('player:width'); - } - - /** - * {@inheritdoc} - */ - public function getHeight() - { - return $this->bag->get('player:height'); - } -} diff --git a/src/QueryResult.php b/src/QueryResult.php new file mode 100644 index 00000000..1c60eecf --- /dev/null +++ b/src/QueryResult.php @@ -0,0 +1,156 @@ + */ + private array $nodes = []; + + /** + * @param DOMNodeList $result + */ + public function __construct(DOMNodeList $result, Extractor $extractor) + { + /** @var list $nodeArray */ + $nodeArray = iterator_to_array($result, false); + $this->nodes = $nodeArray; + $this->extractor = $extractor; + } + + public function node(): ?DOMElement + { + $firstNode = $this->nodes[0] ?? null; + return $firstNode instanceof DOMElement ? $firstNode : null; + } + + /** + * @return list + */ + public function nodes(): array + { + return $this->nodes; + } + + /** + * @param Closure(DOMNode): bool $callback + */ + public function filter(Closure $callback): self + { + $this->nodes = array_values(array_filter($this->nodes, $callback)); + + return $this; + } + + /** + * @return mixed + */ + public function get(?string $attribute = null) + { + $node = $this->node(); + + if ($node === null) { + return null; + } + + return $attribute !== null ? self::getAttribute($node, $attribute) : $node->nodeValue; + } + + /** + * @return list + */ + public function getAll(?string $attribute = null): array + { + $nodes = $this->nodes(); + + return array_values(array_filter( + array_map( + function(\DOMNode $node) use ($attribute) { + if (!$node instanceof DOMElement) { + return $attribute !== null ? null : $node->nodeValue; + } + return $attribute !== null ? self::getAttribute($node, $attribute) : $node->nodeValue; + }, + $nodes + ), + fn($val) => $val !== null && $val !== '' + )); + } + + public function str(?string $attribute = null): ?string + { + $value = $this->get($attribute); + + if (!is_string($value) && !is_numeric($value)) { + return null; + } + + $cleaned = clean((string)$value); + return $cleaned !== '' ? $cleaned : null; + } + + /** + * @return list + */ + public function strAll(?string $attribute = null): array + { + return array_values(array_filter(array_map(function($value) { + if (!is_string($value) && !is_numeric($value)) { + return null; + } + $cleaned = clean((string)$value); + return $cleaned !== '' ? $cleaned : null; + }, $this->getAll($attribute)), fn($v) => $v !== null)); + } + + public function int(?string $attribute = null): ?int + { + $value = $this->get($attribute); + + if ($value === null || $value === '' || $value === false) { + return null; + } + + return is_numeric($value) ? (int) $value : null; + } + + public function url(http://github.com/?string%20$attribute%20=%20null): ?UriInterface + { + $value = $this->get($attribute); + + if (!is_string($value) || $value === '') { + return null; + } + + try { + return $this->extractor->resolveUri($value); + } catch (Throwable $error) { + return null; + } + } + + private static function getAttribute(DOMElement $node, string $name): ?string + { + //Don't use $node->getAttribute() because it does not work with namespaces (ex: xml:lang) + $attributes = $node->attributes; + + for ($i = 0; $i < $attributes->length; ++$i) { + $attribute = $attributes->item($i); + + if ($attribute !== null && $attribute->name === $name) { + return $attribute->nodeValue; + } + } + + return null; + } +} diff --git a/src/Request.php b/src/Request.php deleted file mode 100644 index 67fffd43..00000000 --- a/src/Request.php +++ /dev/null @@ -1,270 +0,0 @@ -getInterfaceNames())) { - throw new \InvalidArgumentException('The resolver class must implement the Embed\\RequestResolvers\\RequestResolverInterface interface'); - } - - $this->resolverClass = $resolverClass; - } - - $this->resolverConfig = array_replace($this->resolverConfig, $resolverConfig); - $this->startingUrl = new Url($url); - $this->parseUrl($url); - } - - /** - * Magic method to clean cache on clone the request. - */ - public function __clone() - { - $this->xmlContent = $this->jsonContent = $this->htmlContent = $this->resolver = null; - } - - /** - * Returns the current resolver - * It also create a new resolver if it's not exists. - * - * @return RequestResolvers\RequestResolverInterface - */ - public function getResolver() - { - if ($this->resolver === null) { - $this->resolver = new $this->resolverClass(UrlRedirect::resolve($this->buildUrl()), $this->resolverConfig); - $this->parseUrl($this->resolver->getUrl()); - } - - return $this->resolver; - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - if ($this->resolver === null) { - $this->getResolver(); - } - - return parent::getUrl(); - } - - /** - * Creates and returns an Url clone. - * - * @return Url - */ - public function createUrl() - { - return new Url($this->getUrl()); - } - - /** - * Creates a new request with the same configuration than this. - * - * @param string $url - * - * @return Request - */ - public function withUrl($url) - { - $clone = clone $this; - - $clone->parseUrl($this->getAbsolute($url)); - - return $clone; - } - - /** - * Check if the url match with a specific pattern. The patterns only accepts * and ? - * - * @param string|array $patterns The pattern or an array with various patterns - * - * @return bool True if the url match, false if not - */ - public function match($patterns) - { - return $this->startingUrl->match($patterns) || parent::match($patterns); - } - - /** - * Return ClassName for domain. - * - * Domains started with numbers will get N prepended to their class name. - * - * @return string - */ - public function getClassNameForDomain() - { - $className = str_replace(array('-', ' '), '', ucwords(strtolower($this->getDomain()))); - if (is_numeric(mb_substr($className, 0, 1))) { - $className = 'N'.$className; - } - - return $className; - } - - /** - * Return the http request info (for debug purposes). - * - * @return array - */ - public function getRequestInfo() - { - return $this->getResolver()->getRequestInfo(); - } - - /** - * Get the http code of the url. - * - * @return int The http code - */ - public function getHttpCode() - { - return $this->getResolver()->getHttpCode(); - } - - /** - * Get the content-type of the url. - * - * @return string|null The content-type header or null - */ - public function getMimeType() - { - return $this->getResolver()->getMimeType(); - } - - /** - * Get the content of the url. - * - * @return string|false The content or false - */ - public function getContent() - { - return $this->getResolver()->getcontent(); - } - - /** - * Get the content of the url as a DOMDocument object. - * - * @return \DOMDocument|false - */ - public function getHtmlContent() - { - if ($this->htmlContent === null) { - try { - if (($content = $this->getContent()) === '') { - return $this->htmlContent = false; - } - - $errors = libxml_use_internal_errors(true); - $this->htmlContent = new \DOMDocument(); - - if ((mb_detect_encoding($content) === 'UTF-8') && mb_check_encoding($content, 'UTF-8')) { - $content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'); - $content = preg_replace('/]*>/', '', $content); - } - - $this->htmlContent->loadHTML($content); - libxml_use_internal_errors($errors); - } catch (\Exception $E) { - return $this->htmlContent = false; - } - } - - return $this->htmlContent; - } - - /** - * Get the content of the url as an array from json. - * - * @return false|array The content or false - */ - public function getJsonContent() - { - if ($this->jsonContent === null) { - try { - if (($content = $this->getContent()) === '') { - return $this->jsonContent = false; - } - - $this->jsonContent = json_decode($content, true); - } catch (\Exception $E) { - return $this->jsonContent = false; - } - } - - return $this->jsonContent; - } - - /** - * Get the content of the url as an XML element. - * - * @return false|\SimpleXMLElement The content or false - */ - public function getXMLContent() - { - if ($this->xmlContent === null) { - try { - if (($content = $this->getContent()) === '') { - return $this->xmlContent = false; - } - $errors = libxml_use_internal_errors(true); - $this->xmlContent = new \SimpleXMLElement($content); - libxml_use_internal_errors($errors); - } catch (\Exception $E) { - return $this->xmlContent = false; - } - } - - return $this->xmlContent; - } - - /** - * Check if the response is valid or not. - * - * @param array $validCodes - * - * @return bool True if it's valid, false if not - */ - public function isValid(array $validCodes = null) - { - if ($validCodes === null) { - return $this->getHttpCode() === 200; - } - - return in_array($this->getHttpCode(), $validCodes, true); - } -} diff --git a/src/RequestResolvers/Curl.php b/src/RequestResolvers/Curl.php deleted file mode 100644 index 8c67c663..00000000 --- a/src/RequestResolvers/Curl.php +++ /dev/null @@ -1,198 +0,0 @@ - 20, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_TIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - CURLOPT_ENCODING => '', - CURLOPT_AUTOREFERER => true, - CURLOPT_USERAGENT => 'Embed PHP Library', - CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, - ]; - - public static $binaryContentTypes = [ - '#image/.*#', - '#application/(pdf|x-download|zip|pdf|msword|vnd\\.ms|postscript|octet-stream|ogg|x-iso9660-image)#', - '#application/x-zip.*#', - ]; - - /** - * {@inheritdoc} - */ - public function __construct($url, array $config) - { - $this->url = $url; - $this->config = $config + $this->config; - } - - /** - * {@inheritdoc} - */ - public function getUrl() - { - return $this->getResult('url'); - } - - /** - * {@inheritdoc} - */ - public function getHttpCode() - { - return intval($this->getResult('http_code')); - } - - /** - * {@inheritdoc} - */ - public function getMimeType() - { - return $this->getResult('mime_type'); - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - if ($this->content === null) { - $this->resolve(); - } - - return $this->content; - } - - /** - * {@inheritdoc} - */ - public function getRequestInfo() - { - if ($this->result === null) { - $this->resolve(); - } - - return $this->result; - } - - /** - * Get the result of the http request. - * - * @param string $name Parameter name - * - * @return null|string The result info - */ - protected function getResult($name) - { - if ($this->result === null) { - $this->resolve(); - } - - return isset($this->result[$name]) ? $this->result[$name] : null; - } - - /** - * Resolves the current url and get the content and other data. - */ - protected function resolve() - { - $this->content = ''; - $this->isBinary = null; - - if (!self::$tmpCookies) { - self::$tmpCookies = str_replace('//', '/', sys_get_temp_dir().'/embed-cookies.txt'); - - if (is_file(self::$tmpCookies)) { - if (!is_writable(self::$tmpCookies)) { - throw new EmbedException(sprintf('The temporary cookies file "%s" is not writable', self::$tmpCookies)); - } - } elseif (!is_writable(dirname(self::$tmpCookies))) { - throw new EmbedException(sprintf('The temporary folder "%s" is not writable', dirname(self::$tmpCookies))); - } - } - - $connection = curl_init(); - - curl_setopt_array($connection, [ - CURLOPT_RETURNTRANSFER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_URL => $this->url, - CURLOPT_COOKIEJAR => self::$tmpCookies, - CURLOPT_COOKIEFILE => self::$tmpCookies, - CURLOPT_HEADERFUNCTION => [$this, 'headerCallback'], - CURLOPT_WRITEFUNCTION => [$this, 'writeCallback'], - ] + $this->config); - - $result = curl_exec($connection); - - $this->result = curl_getinfo($connection) ?: []; - - if (!$result) { - $this->result['error'] = curl_error($connection); - $this->result['error_number'] = curl_errno($connection); - } - - curl_close($connection); - - if (($content_type = $this->getResult('content_type'))) { - if (strpos($content_type, ';') !== false) { - list($mimeType, $charset) = explode(';', $content_type); - - $this->result['mime_type'] = $mimeType; - - $charset = substr(strtoupper(strstr($charset, '=')), 1); - - if (!empty($charset) && !empty($this->content) && ($charset !== 'UTF-8')) { - $this->content = mb_convert_encoding($this->content, 'UTF-8', $charset); - } - } elseif (strpos($content_type, '/') !== false) { - $this->result['mime_type'] = $content_type; - } - } - } - - protected function headerCallback($connection, $string) - { - if (strpos($string, ':')) { - list($name, $value) = array_map('trim', explode(':', $string, 2)); - - if (strtolower($name) === 'content-type') { - $this->isBinary = false; - - foreach (self::$binaryContentTypes as $regex) { - if (preg_match($regex, strtolower($value))) { - $this->isBinary = true; - break; - } - } - } - } - - return strlen($string); - } - - protected function writeCallback($connection, $string) - { - if ($this->isBinary) { - return 0; - } - - $this->content .= $string; - - return strlen($string); - } -} diff --git a/src/RequestResolvers/Guzzle5.php b/src/RequestResolvers/Guzzle5.php deleted file mode 100644 index 38e43304..00000000 --- a/src/RequestResolvers/Guzzle5.php +++ /dev/null @@ -1,115 +0,0 @@ - false, - 'timeout' => 10, - 'connect_timeout' => 20, - 'headers' => [ - 'User-Agent' => 'Embed PHP Library', - ], - 'allow_redirects' => [ - 'max' => 20, - 'referer' => true, - ], - ]; - - /** - * Constructor. Sets the url. - * - * @param string $url The url value - * @param array $config The resolver configuration - */ - public function __construct($url, array $config) - { - $this->client = isset($config['client']) ? $config['client'] : new Client([ - 'defaults' => $this->defaultConfig, - ]); - - $this->request = $this->client->createRequest('GET', $url); - } - - /** - * Get the http code of the url, for example: 200. - * - * @return int The http code - */ - public function getHttpCode() - { - return $this->getResponse()->getStatusCode(); - } - - /** - * Get the content-type of the url, for example: text/html. - * - * @return string The content-type header or null - */ - public function getMimeType() - { - return $this->getResponse()->getHeader('Content-Type'); - } - - /** - * Get the content of the url. - * - * @return string The content or false - */ - public function getContent() - { - return $this->getResponse()->getBody()->getContents(); - } - - /** - * Return the final url (after all possible redirects). - * - * @return string The final url - */ - public function getUrl() - { - return $this->getResponse()->getEffectiveUrl(); - } - - /** - * Return the http request info (for debug purposes). - * - * @return array - */ - public function getRequestInfo() - { - return $this->request->getConfig(); - } - - /** - * Get the result of the http request. - * - * @return Response - */ - protected function getResponse() - { - if ($this->response === null) { - $this->response = $this->client->send($this->request); - } - - return $this->response; - } -} diff --git a/src/RequestResolvers/RequestResolverInterface.php b/src/RequestResolvers/RequestResolverInterface.php deleted file mode 100644 index 8107be41..00000000 --- a/src/RequestResolvers/RequestResolverInterface.php +++ /dev/null @@ -1,52 +0,0 @@ -getMimeType()) { - case 'text/xml': - case 'text/html': - case 'application/xml': - case 'application/atom+xml': - case 'application/rss+xml': - return true; - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function __construct(Request $request) - { - $this->request = $request; - - if (($xml = $this->request->getXMLContent())) { - $this->data = self::parseRss($xml) ?: self::parseAtom($xml); - } - } - - /** - * {@inheritdoc} - */ - public function isValid() - { - return is_array($this->data); - } - - /** - * {@inheritdoc} - */ - public function getSourceUrl() - { - return $this->request->getUrl(); - } - - /** - * {@inheritdoc} - */ - public function getProviderUrl() - { - return !empty($this->data['url']) ? $this->data['url'] : ($this->request->getScheme().'://'.$this->request->getHost()); - } - - /** - * {@inheritdoc} - */ - public function getItems() - { - return isset($this->data['items']) ? (array) $this->data['items'] : []; - } - - /** - * Search data from Rss. - * - * @param \SimpleXMLElement $xml - * - * @return false|array - */ - protected static function parseRss(\SimpleXMLElement $xml) - { - if (isset($xml->item)) { - $items = $xml->item; - } elseif (isset($xml->channel)) { - $items = $xml->channel->item; - } else { - return false; - } - - return [ - 'url' => (string) $xml->channel->link, - 'items' => self::getRssItems($items), - ]; - } - - /** - * Search items from XML. - * - * @param \SimpleXMLElement $items - * - * @return array - */ - protected static function getRssItems(\SimpleXMLElement $items) - { - $rssItems = []; - - $namespaces = $items->getNamespaces(true); - - foreach ($items as $item) { - $rssItem = [ - 'url' => null, - 'originUrl' => null, - 'pubdate' => null, - ]; - - $rssItem['url'] = (string) $item->link; - $rssItem['originUrl'] = ((string) $item->origLink ?: (string) $item->comments); - $rssItem['pubdate'] = ((string) $item->pubdate ?: (string) $item->pubDate); - - if (!$rssItem['pubdate'] && isset($namespaces['dc']) && ($children = $item->children($namespaces['dc']))) { - $rssItem['pubdate'] = (string) $children->date; - } - - if (!$rssItem['originUrl'] && isset($namespaces['feedburner']) && ($children = $item->children($namespaces['feedburner']))) { - $rssItem['originUrl'] = (string) $children->origLink; - } - - if ($rssItem['url']) { - $rssItems[] = $rssItem; - } - } - - return $rssItems; - } - - /** - * Search data from Atom xml. - * - * @param \SimpleXMLElement $xml - * - * @return false|array - */ - protected static function parseAtom(\SimpleXMLElement $xml) - { - if (!isset($xml->entry)) { - return false; - } - - $url = ''; - - foreach ($xml->link as $link) { - $attributes = $link->attributes(); - - if (empty($attributes->href) || ((string) $attributes->rel === 'self')) { - continue; - } - $url = (string) $attributes->href; - break; - } - - return [ - 'url' => $url, - 'items' => self::getAtomEntries($xml->entry), - ]; - } - - /** - * Search entries from Atom xml. - * - * @param \SimpleXMLElement $entries - * - * @return array - */ - protected static function getAtomEntries(\SimpleXMLElement $entries) - { - $items = []; - - foreach ($entries as $entry) { - $item = [ - 'url' => null, - 'originUrl' => null, - 'pubdate' => null, - ]; - - if ($entry->created) { - $item['pubdate'] = (string) $entry->created; - } elseif ($entry->updated) { - $item['pubdate'] = (string) $entry->updated; - } elseif ($entry->modified) { - $item['pubdate'] = (string) $entry->modified; - } - - foreach ($entry->link as $link) { - $attributes = $link->attributes(); - - if (!empty($attributes->href) && ((string) $attributes->rel === 'alternate')) { - $item['url'] = (string) $attributes->href; - break; - } - } - - foreach ($entry->link as $link) { - $attributes = $link->attributes(); - - if (!empty($attributes->href) && ((string) $attributes->rel === 'comments')) { - $item['originUrl'] = (string) $attributes->href; - break; - } - } - - if (!$item['url'] && isset($link)) { - $attributes = $link->attributes(); - - if (!empty($attributes->href)) { - $item['url'] = (string) $attributes->href; - } - } - - if ($item['url']) { - $items[] = $item; - } - } - - return $items; - } -} diff --git a/src/Sources/Source.php b/src/Sources/Source.php deleted file mode 100644 index 3fc9e7bc..00000000 --- a/src/Sources/Source.php +++ /dev/null @@ -1,20 +0,0 @@ -parseUrl($url); - } - - /** - * Returns the url. - * - * @return string - */ - public function __toString() - { - return $this->getUrl(); - } - - /** - * Return the url. - * - * @return string The current url - */ - public function getUrl() - { - return $this->buildUrl(); - } - - /** - * Check if the url match with a specific pattern. The patterns only accepts * and ? - * - * @param string|array $patterns The pattern or an array with various patterns - * - * @return bool True if the url match, false if not - */ - public function match($patterns) - { - if (!is_array($patterns)) { - $patterns = [$patterns]; - } - - $url = $this->getUrl(); - - foreach ($patterns as $pattern) { - $pattern = str_replace(['\\*', '\\?'], ['.+', '?'], preg_quote($pattern, '|')); - - if (preg_match('|^'.$pattern.'$|i', $url)) { - return true; - } - } - - return false; - } - - /** - * Return the content of the url (for embedded images). - * - * @return string The content or null - */ - public function getContent() - { - return isset($this->info['content']) ? $this->info['content'] : null; - } - - /** - * Return the extension of the url (html, php, jpg, etc). - * - * @return string The scheme or null - */ - public function getExtension() - { - return isset($this->info['extension']) ? $this->info['extension'] : null; - } - - /** - * Returns a clone with other extension. - * - * @param string $extension - * - * @return Url - */ - public function withExtension($extension) - { - $clone = clone $this; - $clone->info['extension'] = $extension; - - if (empty($clone->info['file'])) { - $clone->info['file'] = array_pop($clone->info['path']); - } - - return $clone; - } - - /** - * Return the scheme of the url (for example http, https, ftp, etc). - * - * @return string The scheme or null - */ - public function getScheme() - { - return isset($this->info['scheme']) ? $this->info['scheme'] : null; - } - - /** - * Returns a clone with other scheme. - * - * @param string $scheme - * - * @return Url - */ - public function withScheme($scheme) - { - $clone = clone $this; - $clone->info['scheme'] = $scheme; - - return $clone; - } - - /** - * Return the host of the url (for example: google.com). - * - * @return string The host or null - */ - public function getHost() - { - return isset($this->info['host']) ? $this->info['host'] : null; - } - - /** - * Returns a clone with other host. - * - * @param string $host - * - * @return Url - */ - public function withHost($host) - { - $clone = clone $this; - $clone->info['host'] = $host; - - return $clone; - } - - /** - * Return the domain of the url (for example: google). - * - * @param bool $first_level True to return the first level domain (.com, .es, etc) - * - * @return string - */ - public function getDomain($first_level = false) - { - $host = $this->getHost(); - - if (empty($host)) { - return ''; - } - - $host = array_reverse(explode('.', $host)); - - switch (count($host)) { - case 1: - return $host[0]; - - case 2: - return $first_level ? ($host[1].'.'.$host[0]) : $host[1]; - - default: - if ($first_level) { - return ($host[1] === 'co' || $host[1] === 'com') ? ($host[2].'.'.$host[1].'.'.$host[0]) : ($host[1].'.'.$host[0]); - } - - return ($host[1] === 'co' || $host[1] === 'com') ? $host[2] : $host[1]; - } - } - - /** - * Return a specific directory position in the path of the url. - * - * @param int $position The position of the directory (0 based index) - * - * @return string|null - */ - public function getDirectoryPosition($position) - { - if ($position === count($this->info['path'])) { - return $this->info['file']; - } - - return isset($this->info['path'][$position]) ? $this->info['path'][$position] : null; - } - - /** - * Returns a clone with other directory in a specific position. - * - * @param int|null $key The position of the subdirectory (0 based index). - * @param string $value The new value - * - * @return Url - */ - public function withDirectoryPosition($key, $value) - { - $clone = clone $this; - - if ($key === count($clone->info['path'])) { - $clone->info['file'] = $value; - - return $clone; - } - - $clone->info['path'][$key] = $value; - - return $clone; - } - - /** - * Return all directories. - * - * @return string - */ - public function getDirectories() - { - return !empty($this->info['path']) ? '/'.implode('/', $this->info['path']).'/' : '/'; - } - - /** - * Slice path. - * - * @param int $offset - * @param int|null $length - * - * @return array - */ - public function getSlicePath($offset, $length = null) - { - $array = explode('/', $this->getPath()); - - if (empty($array[0])) { - array_shift($array); - } - - return array_slice($array, $offset, $length); - } - - /** - * Return the url path. - * - * @return string - */ - public function getPath() - { - $path = !empty($this->info['path']) ? '/'.implode('/', array_map('urlencode', $this->info['path'])).'/' : '/'; - - if (isset($this->info['file'])) { - $path .= $this->info['file']; - - if (isset($this->info['extension'])) { - $path .= '.'.$this->info['extension']; - } - } - - return $path; - } - - /** - * Returns a clone with other path. - * - * @param string $path - * - * @return Url - */ - public function withPath($path) - { - $clone = clone $this; - - $clone->setPath($path); - - return $clone; - } - - /** - * Returns a clone with path appended. - * - * @param string $path - * - * @return Url - */ - public function withAddedPath($path) - { - $path = $this->getPath().'/'.$path; - - return $this->withPath($path); - } - - /** - * Check if the url has a query parameter. - * - * @param string $name - * - * @return bool - */ - public function hasQueryParameter($name) - { - return isset($this->info['query'][$name]); - } - - /** - * Returns all query parameters. - * - * @return array - */ - public function getQueryParameters() - { - return $this->info['query']; - } - - /** - * Returns a query parameter value. - * - * @param string $name - * - * @return string|null - */ - public function getQueryParameter($name) - { - return isset($this->info['query'][$name]) ? $this->info['query'][$name] : null; - } - - /** - * Returns a clone with a new query parameter. - * - * @param string $name The parameter name - * @param string $value The parameter value - * - * @return Url - */ - public function withQueryParameter($name, $value) - { - $clone = clone $this; - - $clone->info['query'][$name] = $value; - - return $clone; - } - - /** - * Returns a clone with new query parameters merged. - * - * @param array $parameters - * - * @return Url - */ - public function withAddedQueryParameters(array $parameters) - { - $clone = clone $this; - - $clone->info['query'] = empty($clone->info['query']) ? $parameters : array_replace($clone->info['query'], $parameters); - - return $clone; - } - - /** - * Returns a clone with new query parameters. - * - * @param array $parameters - * - * @return Url - */ - public function withQueryParameters(array $parameters) - { - $clone = clone $this; - - $clone->info['query'] = $parameters; - - return $clone; - } - - /** - * Return the url fragment. - * - * @return string - */ - public function getFragment() - { - return isset($this->info['fragment']) ? $this->info['fragment'] : null; - } - - /** - * Build the url using the splitted data. - */ - protected function buildUrl() - { - $url = ''; - - if (isset($this->info['content'])) { - return 'data:'.$this->info['content']; - } - - if (isset($this->info['scheme'])) { - $url .= $this->info['scheme'].'://'; - } - - if (isset($this->info['host'])) { - $url .= $this->info['host']; - } - - $url .= $this->getPath(); - - if (!empty($this->info['query'])) { - $url .= '?'.http_build_query($this->info['query']); - } - if (isset($this->info['fragment'])) { - $url .= '#'.$this->info['fragment']; - } - - return $url; - } - - /** - * Parse an url and split into different pieces. - * - * @param string $url The url to parse - */ - protected function parseUrl($url) - { - if (strpos($url, '//') === 0) { - $url = "http:$url"; - } - - $this->info = parse_url(http://github.com/$url); - - if (isset($this->info['path'])) { - $this->setPath($this->info['path']); - } - - if (empty($this->info['query'])) { - $this->info['query'] = []; - - return; - } - - // Fix dots and other characters used in query's variables names - // https://github.com/oscarotero/Embed/issues/101 - $queryString = preg_replace_callback('/(^|(?<=&))[^=[&]+/', function ($key) { - return bin2hex(urldecode($key[0])); - }, $this->info['query']); - - parse_str($queryString, $query); - - $this->info['query'] = []; - - foreach ((array) $query as $key => $value) { - $this->info['query'][hex2bin($key)] = $value; - } - - array_walk_recursive($this->info['query'], function (&$value) { - $value = urldecode($value); - }); - } - - /** - * Return an absolute url based in a relative. - * - * @return string The absolute url - */ - public function getAbsolute($url) - { - if (empty($url)) { - return ''; - } - - if (strpos($url, 'data:') === 0) { - return $url; - } - - if (preg_match('|^\w+://|', $url)) { - return $url; - } - - if (strpos($url, '://') === 0) { - return $this->getScheme().$url; - } - - if (strpos($url, '//') === 0) { - return $this->getScheme().":$url"; - } - - if ($url[0] === '/') { - return $this->getScheme().'://'.$this->getHost().$url; - } - - return $this->getScheme().'://'.$this->getHost().$this->getDirectories().$url; - } - - /** - * Parses and adds path and file value. - * - * @param string $path - */ - private function setPath($path) - { - if ($this->getScheme() === 'data') { - $this->info['content'] = $path; - $this->info['path'] = $this->info['file'] = $this->info['extension'] = null; - - return; - } - - $parts = pathinfo($path); - - $this->info['path'] = []; - - if (isset($parts['dirname'])) { - foreach (explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $parts['dirname'])) as $dir) { - $dir = trim(urldecode($dir)); - - if ($dir !== '') { - $this->info['path'][] = $dir; - } - } - } - - $this->info['file'] = isset($parts['filename']) ? $parts['filename'] : null; - $this->info['extension'] = isset($parts['extension']) ? $parts['extension'] : null; - $this->info['content'] = null; - - // bugfix /wiki/Supernatural_(U.S._TV_series) is parsed as: - // path: /wiki/ - // file: Supernatural_(U.S - // extension: _TV_series) - if (!empty($this->info['extension']) && !preg_match('/^\w+$/', $this->info['extension'])) { - $this->info['file'] .= '.'.$this->info['extension']; - $this->info['extension'] = null; - } - } -} diff --git a/src/UrlRedirect.php b/src/UrlRedirect.php deleted file mode 100644 index 9d4c18ff..00000000 --- a/src/UrlRedirect.php +++ /dev/null @@ -1,83 +0,0 @@ - 'https?://www.google.com/url*', - 'googleTranslator' => 'https?://translate.google.com/translate*', - 'hashBang' => '*#!*', - ]; - - /** - * Resolve the url redirection. - * - * @param string $oldUrl Url to resolve - * - * @return string - */ - public static function resolve($oldUrl) - { - $url = new Url($oldUrl); - - foreach (static::$urls as $method => $matches) { - if ($url->match($matches)) { - return static::$method($url); - } - } - - return $oldUrl; - } - - /** - * Resolve a google redirection url. - * - * @param Url $url - * - * @return string - */ - protected static function google(Url $url) - { - if (($urlString = $url->getQueryParameter('url'))) { - return $urlString; - } - - return $url->getUrl(); - } - - /** - * Resolve a google translation url. - * - * @param Url $url - * - * @return string - */ - protected static function googleTranslator(Url $url) - { - if (($urlString = $url->getQueryParameter('u'))) { - return $urlString; - } - - return $url->getUrl(); - } - - /** - * Resolve an url with hashbang. - * - * @param Url $url - * - * @return string - */ - protected static function hashBang(Url $url) - { - if (($path = preg_replace('|^(/?!)|', '', $url->getFragment()))) { - return $url->withPath($url->getPath().$path)->getUrl(); - } - - return $url->getUrl(); - } -} diff --git a/src/Utils.php b/src/Utils.php deleted file mode 100644 index f60e6bb3..00000000 --- a/src/Utils.php +++ /dev/null @@ -1,410 +0,0 @@ -getElementsByTagName('meta') as $meta) { - $name = trim(strtolower($meta->getAttribute('property') ?: $meta->getAttribute('name'))); - $value = $meta->getAttribute('content') ?: $meta->getAttribute('value'); - $metas[] = [$name, $value, $meta]; - } - - return $metas; - } - - /** - * Extract all link elements from html. - * - * @param \DOMDocument $html - * @param string $tagName - * - * @return array with subarrays [rel, href, element] - */ - public static function getLinks(\DOMDocument $html, $tagName = 'link') - { - $links = []; - - foreach ($html->getElementsByTagName($tagName) as $link) { - if ($link->hasAttribute('rel') && $link->hasAttribute('href')) { - $rel = trim(strtolower($link->getAttribute('rel'))); - $href = $link->getAttribute('href'); - - $links[] = [$rel, $href, $link]; - } - } - - return $links; - } - - /** - * Search and returns all data retrieved by the providers. - * - * @param null|array $providers The providers used to retrieve the data - * @param string $name The data name (title, description, image, etc) - * @param Url $url The base url used to resolve relative urls - * - * @return array - */ - public static function getData(array $providers, $name, Url $url = null) - { - $method = 'get'.$name; - $values = []; - - foreach ($providers as $key => $provider) { - $value = $provider->$method(); - if (empty($value)) { - continue; - } - - if (!is_array($value)) { - $value = [$value]; - } - - foreach ($value as $v) { - if ($url) { - $v = $url->getAbsolute($v); - } - - if (!isset($values[$v])) { - $values[$v] = [ - 'value' => $v, - 'providers' => [$key], - ]; - } elseif (!in_array($key, $values[$v]['providers'], true)) { - $values[$v]['providers'][] = $key; - } - } - } - - return array_values($values); - } - - /** - * Order the data by provider. - * - * @param array $values The array provided by self::getData() - * - * @return array - */ - public static function sortByProviders(array $values) - { - $sorted = []; - - foreach ($values as $value) { - foreach ($value['providers'] as $provider) { - if (!isset($sorted[$provider])) { - $sorted[$provider] = [$value]; - } else { - $sorted[$provider][] = $value; - } - } - } - - return $sorted; - } - - /** - * Unshifts a new value if it does not exists. - * - * @param array $values The array provided by self::getData() - * @param array $value The value to insert - */ - public static function unshiftValue(array &$values, $value) - { - $key = self::searchValue($values, $value['value'], true); - - if ($key === false) { - return array_unshift($values, $value); - } - - $value = array_merge($values[$key], $value); - - array_splice($values, $key, 1); - - return array_unshift($values, $value); - } - - /** - * Search by a value and returns its key. - * - * @param array $values The array provided by self::getData() - * @param string $value The value to search - * @param bool $returnKey Whether or not return the key instead the value - * - * @return array|false - */ - public static function searchValue(array $values, $value, $returnKey = false) - { - foreach ($values as $k => $each) { - if ($each['value'] === $value) { - return $returnKey ? $k : $each; - } - } - - return false; - } - - /** - * Returns the first value if exists. - * - * @param array $values The array provided by self::getData() - * @param bool $returnKey Whether or not return the key instead the value - * - * @return string|null - */ - public static function getFirstValue(array $values, $returnKey = false) - { - if (isset($values[0])) { - return $returnKey ? 0 : $values[0]['value']; - } - } - - /** - * Returns values as array. - * - * @param array $values The array provided by self::getData() - * @param bool $returnKey Whether or not return the key instead the value - * - * @return array - */ - public static function getAllValues(array $values, $returnKey = false) - { - if ($returnKey) { - return array_keys($values); - } - $return_value = []; - foreach ($values as $value) { - $return_value[] = $value['value']; - } - - return $return_value; - } - - /** - * Returns the most popular value in an array. - * - * @param array $values The array provided by self::getData() - * @param bool $returnKey Whether or not return the key instead the value - * - * @return mixed - */ - public static function getMostPopularValue(array $values, $returnKey = false) - { - $mostPopular = null; - - foreach ($values as $k => $value) { - if ($mostPopular === null || count($value['providers']) > count($values[$mostPopular]['providers'])) { - $mostPopular = $k; - } - } - - if (isset($mostPopular)) { - return $returnKey ? $mostPopular : $values[$mostPopular]['value']; - } - } - - /** - * Returns the bigger value. - * - * @param array $values The array provided by self::getData() - * @param bool $returnKey Whether or not return the key instead the value - * - * @return null|string - */ - public static function getBiggerValue(array $values, $returnKey = false) - { - $bigger = null; - - foreach ($values as $k => $value) { - if ($bigger === null || $value['size'] > $values[$bigger]['size']) { - $bigger = $k; - } - } - - if ($bigger !== null) { - return $returnKey ? $bigger : $values[$bigger]['value']; - } - } - - /** - * Creates a '; - } - - /** - * Creates an
+ + + + + + + + + + + + ' +]; diff --git a/tests/cache/archive.org.details-librivoxaudio.php b/tests/cache/archive.org.details-librivoxaudio.php new file mode 100644 index 00000000..1951c370 --- /dev/null +++ b/tests/cache/archive.org.details-librivoxaudio.php @@ -0,0 +1,10095 @@ + [ + 'server' => [ + 'nginx/1.16.1 (Ubuntu)' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:21:44 GMT' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'set-cookie' => [ + 'collections=librivoxaudio; expires=Fri, 01-Oct-2021 15:21:44 GMT; Max-Age=15552000; path=/; domain=.archive.org', + 'donation-identifier=274c7691e064ea7415d20dd3223704b2; expires=Mon, 04-Apr-2022 15:21:44 GMT; Max-Age=31536000; path=/; domain=.archive.org', + 'abtest-identifier=6fe8263e2fc82c1eaedc654804e3d81b; expires=Mon, 04-Apr-2022 15:21:44 GMT; Max-Age=31536000; path=/; domain=.archive.org', + 'PHPSESSID=aelqllbh87uhe496id3g8ksto0; path=/; domain=.archive.org' + ], + 'strict-transport-security' => [ + 'max-age=15724800' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://archive.org/details/librivoxaudio' + ], + 'X-Request-Time' => [ + '1.164 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + The LibriVox Free Audiobook Collection : Free Audio : Free Download, Borrow and Streaming : Internet Archive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Skip to main content + + +
+ + +
+ + + +
+ + + +
+
+ + +
+
+
+
+
+
+
+
+
+ +
+
+

The LibriVox Free Audiobook Collection

+
+
+
+

LibriVox - founded in 2005 - is a community of volunteers from all over the world who record public domain texts: poetry, short stories, whole books, even dramatic works, in many different languages. + +All LibriVox recordings are in the public domain in the USA and available as free downloads on the internet. If you are not in the USA, please check your country\'s copyright law before downloading. + +

+
+
+
+
+ +
+ + + rss RSS +
+ + + +
+
+ +
+
+ +
+ +
+ +
+
+
+
+
+ + +
+
+ + +
+ +
+ + + +
+ + +
+
Media Type
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
Year
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
Topics & SubjectsShow sorted alphabetically
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
Collection
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
CreatorShow sorted alphabetically
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
Language
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+ + +
+
+
+ +
+
+ +
+
+ +
+ + SHOW DETAILS +
+ +
+ up-solid down-solid
+
+ +
+ +
+
+
+ + +
+
+
+
+ eye
+
+
Title
+
Date Reviewed
+
Creator
+
+
+
+ + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Lewis Carroll +
+
+ +
+
+ audio
+ +
+ eye 14.1M +
+ +
+ favorite 214
+ +
+ comment 4
+
+ +
+ + +
+
+
+ Librivox recording of Alice\'s Adventures in Wonderland, by Lewis Carroll. A children\'s classic! Read by: Chapter 01 Kristen McQuillin Chapter 02 Brad Bush Chapter 03 Roger W. Barnett Chapter 04 Miette Chapter 05 Mark Bradford Chapter 06 Raza Shah Chapter 07 Kara Shallenberg Chapter 08 Kristen McQuillin Chapter 09 MarinaMechanical Chapter 10 Roger W. Barnett Chapter 11 R. Francis Smith Chapter 12 Chris Goringe For further information, including links to online text, reader information, RSS...
favoritefavoritefavoritefavorite ( 4 reviews )
Topics: literature, children, audiobook, librivox
Source: Librivox recording of Gutenberg e-text #11
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sun Tzu +
+
+ +
+
+ audio
+ +
+ eye 13.9M +
+ +
+ favorite 817
+ +
+ comment 24
+
+ +
+ + +
+
+
+ Librivox recording of The Art of War by Sun Tzu, translated by Lionel Giles. Read by Moira Fogarty. "The Art of War is a Chinese military treatise written during the 6th century BC by Sun Tzu. Composed of 13 chapters, each of which is devoted to one aspect of warfare, it has long been praised as the definitive work on military strategies and tactics of its time. The Art of War is one of the oldest and most famous studies of strategy and has had a huge influence on both military planning...
favoritefavoritefavoritefavoritefavorite ( 24 reviews )
Topics: librivox, audiobook, literature, war, Sun Tzu, Sunzi, Lionel Giles
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Doyle, Sir Arthur Conan +
+
+ +
+
+ audio
+ +
+ eye 11.6M +
+ +
+ favorite 361
+ +
+ comment 25
+
+ +
+ + +
+
+
+ Librivox recording of the Adventures of Sherlock Holmes. The Adventures of Sherlock Holmes is a collection of twelve stories by Arthur Conan Doyle, featuring his famous detective. They were originally published in the Strand Magazine from July 1891 to June 1892. The title character was named after famous American poet Oliver Wendell Holmes, Sr. (Summary from Wikipedia) For further information, including links to online text, reader information, RSS feeds, CD cover,m4b or other formats (if...
favoritefavoritefavorite ( 25 reviews )
Topics: librivox, audiobook, literature, Holmes, adventure, Doyle
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Mark Twain +
+
+ +
+
+ audio
+ +
+ eye 11.8M +
+ +
+ favorite 276
+ +
+ comment 24
+
+ +
+ + +
+
+
+ LibriVox recording of The Adventures of Tom Sawyer by Mark Twain. Read by John Greenman. The Adventures of Tom Sawyer (published 1876) is a very well-known and popular story concerning American youth. Mark Twain\'s lively tale of the scrapes and adventures of boyhood is set in St. Petersburg, Missouri, where Tom Sawyer and his friend Huckleberry Finn have the kinds of adventures many boys can imagine: racing bugs during class, impressing girls, with fights and stunts in the schoolyard, getting...
favoritefavoritefavoritefavoritefavorite ( 24 reviews )
Topics: librivox, audiobook, literature
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sir Arthur Conan Doyle +
+
+ +
+
+ audio
+ +
+ eye 5.4M +
+ +
+ favorite 181
+ +
+ comment 7
+
+ +
+ + +
+
+
+ LibriVox recording of The Adventures of Sherlock Holmes, by Sir Arthur Conan Doyle. Read by Mark F. Smith. Dr. Watson chronicles here some of the more interesting detective cases that he and his good friend, Mr. Sherlock Holmes, have encountered during their association. We see the cases unfold as he does, scratch our heads as does he while the evidence is collected, and then marvel at the impeccable observations, remarkable insight, and doggedness which Holmes displays as he teases apart the...
favoritefavoritefavoritefavoritefavorite ( 7 reviews )
Topics: librivox, audiobook, doyle, mystery, sherlock holmes, literature, adventure
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + William Walker Atkinson +
+
+ +
+
+ audio
+ +
+ eye 359,825 +
+ +
+ favorite 65
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of Thought Vibration, or The Law of Attraction in the Thought, by William Walker Atkinson. Read by Algy Pug. William Walker Atkinson (December 5, 1862 – November 22, 1932) was an attorney, merchant, publisher, and author, as well as an occultist and an American pioneer of the New Thought movement. Atkinson was a prolific writer, and his many books achieved wide circulation among New Thought devotees and occult practitioners. He published under several pen names, including...
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, literature, audiobook, William Walker Atkinson, Thought Vibration
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Herman Melville +
+
+ +
+
+ audio
+ +
+ eye 8.7M +
+ +
+ favorite 395
+ +
+ comment 26
+
+ +
+ + +
+
+
+ Librivox recording of Moby Dick, or the Whale, by Herman Melville. Read by Stewart Wills Few things, even in literature, can really be said to be unique -- but Moby Dick is truly unlike anything written before or since. The novel is nominally about the obsessive hunt by the crazed Captain Ahab of the book\'s eponymous white whale. But interspersed in that story are digressions, paradoxes, philosophical riffs on whaling and life, and a display of techniques so advanced for its time that some have...
favoritefavoritefavoritefavoritefavorite ( 26 reviews )
Topics: librivox, audiobook, literature
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Grace Isabel Colbron and Augusta Groner +
+
+ +
+
+ audio
+ +
+ eye 67,543 +
+ +
+ favorite 1
+ +
+ comment 5
+
+ +
+ + +
+
+
+ LibriVox recording of The Case of the Golden Bullet by Grace Isabel Colbron and Augusta Groner. Read by Dawn Larsen Joseph Muller, quiet mannered detective, tries to solve the mystery of a man who died in his study, by a bullet hole in the chest. But all windows and doors were locked, from the inside. (summary by Dawn Larsen) For further information, including links to online text, reader information, RSS feeds, CD cover or other formats (if available), please go to the LibriVox catalog page...
favoritefavoritefavoritefavorite ( 5 reviews )
Topics: librivox, audiobooks, mystery, detective stories, Austria, Joseph Muller
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jane Austen +
+
+ +
+
+ audio
+ +
+ eye 7.4M +
+ +
+ favorite 200
+ +
+ comment 6
+
+ +
+ + +
+
+
+ Librivox recording of Pride and Prejudice , by Jane Austen. For more information on our readers, see our catalog page: http://librivox.org/pride-and-prejudice-by-jane-austen/ Pride and Prejudice is the most famous of Jane Austen\'s novels, and its opening is one of the most famous lines in English literature - "It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife." Its manuscript was first written between 1796 and 1797,...
favoritefavoritefavoritefavoritefavorite ( 6 reviews )
Topics: librivox, audiobook, literature
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + LibriVox Volunteers +
+
+ +
+
+ audio
+ +
+ eye 11.7M +
+ +
+ favorite 33
+ +
+ comment 5
+
+ +
+ + +
+
+
+ Index of pages containing M4B files created by LibriVox Volunteers. UPDATE - 22 FEB 2015 Thanks to an improvement by folks at Internet Archive, M4B files can now be stored together with the other Librivox audio files without causing problems. We will not adding to these pages any more. Main ( 1.7 GB) English page 1 ( 74.5 GB) English page 1A (152 GB) English page 1B ( 30.1 GB) English page 2 (112 GB) English page 3 (137 GB) English page 4 ( 76.6 GB) English page 5 ( 30.7 GB) English page 6 (...
favoritefavoritefavoritefavoritefavorite ( 5 reviews )
Topics: M4B, Librivox, Audiobooks, iPods
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Anna Katharine Green +
+
+ +
+
+ audio
+ +
+ eye 28,671 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of El crimen de Gramercy Park by Anna Katharine Green. (Translated by Unknown.) Read in Spanish by Victor Villarraza Obra maestra de la «madre de la novela de detectives», Anna Katharine Green, conocida como la Agatha Christie victoriana. El misterio de Gramercy Park, publicado en 1897, es la décima novela policíaca de Anna K. Green y la primera en la que se introduce el inolvidable personaje de Amelia Butterworth(precursora de la señorita Marple), dama soltera y...
Topics: librivox, audiobooks, Mystery, miss butterworth, that affair next door
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + LibriVox covermakers +
+
+ +
+
+ audio
+ +
+ eye 7.5M +
+ +
+ favorite 2
+ +
+ comment 0
+
+ +
+ + +
+
+
+ thumb images for Librivox projects
Topics: Librivox, covers, thumb images
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Mark Twain +
+
+ +
+
+ audio
+ +
+ eye 7.9M +
+ +
+ favorite 183
+ +
+ comment 13
+
+ +
+ + +
+
+
+ Librivox recording of Adventures of Huckleberry Finn , by Mark Twain. Read by Annie Coleman . Adventures of Huckleberry Finn (1884) by Mark Twain is one of the truly great American novels, beloved by children, adults, and literary critics alike. The book tells the story of "Huck" Finn (first introduced as Tom Sawyer\'s sidekick in The Adventures of Tom Sawyer ), his friend Jim, and their journey down the Mississippi River on a raft. Both are on the run, Huck from his drunk and abusive...
favoritefavoritefavoritefavoritefavorite ( 13 reviews )
Topics: librivox, audiobook, literature, twain, huckleberry, finn
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Librivox covermakers +
+
+ +
+
+ audio
+ +
+ eye 6.2M +
+ +
+ favorite 0
+ +
+ comment 2
+
+ +
+ + +
+
+
+ Librivox cover art thumbnails
favorite ( 2 reviews )
Topic: thumb images
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sir Arthur Conan Doyle +
+
+ +
+
+ audio
+ +
+ eye 450,146 +
+ +
+ favorite 1
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of El Sabueso de los Baskerville by Sir Arthur Conan Doyle. (Translated by Arturo Costa Álvarez) Read in Spanish by Victor Villarraza El sabueso de los Baskerville , también traducido como El perro de los Baskerville o El mastín de los Baskerville, es la tercera novela de Arthur Conan Doyle que tiene como protagonista principal a Sherlock Holmes. Fue publicada por entregas en el The Strand Magazine entre 1901 y 1902. La novela está principalmente ambientada en Dartmoor,...
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, audiobooks, Sherlock Holmes, dr watson, baskerville
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Alexandre Dumas +
+
+ +
+
+ audio
+ +
+ eye 5.4M +
+ +
+ favorite 164
+ +
+ comment 20
+
+ +
+ + +
+
+
+ Librivox recording of The Count of Monte Cristo , by Alexandre Dumas. The Count of Monte Cristo (French: Le Comte de Monte-Cristo ) is an adventure novel by Alexandre Dumas, père. It is often considered, along with The Three Musketeers , as Dumas\'s most popular work. The writing of the work was completed in 1844. Like many of his novels, it is expanded from the plot outlines suggested by his collaborating ghostwriter Auguste Maquet. The story takes place in France, Italy, islands in the...
favoritefavoritefavorite ( 20 reviews )
Topics: monte cristo, dumas, librivox, audiobook, adventure, romance
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Nicolas Gonner; Nicolas-Edouard Becker; Jean-Baptiste Nau +
+
+ +
+
+ audio
+ +
+ eye 26,583 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Prairieblummen by Nicolas Gonner; Nicolas-Edouard Becker; Jean-Baptiste Nau. Read in Luxembourgish by Sandra Schmit; Sonia Den ëmfangräichste Gedichtband vu Lëtzebuerger, déi am 19. Joerhonnert an d\'USA ausgewandert sinn. Theme sinn Erënnerungen un d\'Heemecht, d\'Liewen an Amerika, d\'Pionéierzäit, d\'Solidaritéit innerhalb vun der Lëtzebuerger Communautéit, d\'Relioun an amerikanesch a lëtzebuergesch Soen a Geschichten. D\'Buch ass 1883 zu Dubuque, Iowa, erauskomm....
Topics: librivox, audiobooks, poetry, folklore, American history, luxembourg, emigration literature,...
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + + + +
+
+ audio
+ +
+ eye 20,907 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox  reading of Harper\'s Young People, Vol. 01, Issue 25, April 20, 1880, by Various. Read in English by springteacher; mleigh; MaybeCordelia; Dulaney High Key Club; Larry Wilson; Michelle Hannah; Jason Gemenetzis and BettyB Harper\'s Young People is an illustrated weekly publication for children that includes short stories, tales from history, natural history, poetry, puzzles, and other fun. This 25th issue of the serial was published on April 20th, 1880 and in its pages it contains the...
Topics: librivox, audiobooks, poetry, children, history, sailor, animals, story, books, short stories,...
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + LibriVox Covermakers +
+
+ +
+
+ audio
+ +
+ eye 4.4M +
+ +
+ favorite 1
+ +
+ comment 0
+
+ +
+ + +
+
+
+ thumb cover images for Librivox
Topics: images, librivox
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Bram Stoker +
+
+ +
+
+ audio
+ +
+ eye 6.2M +
+ +
+ favorite 303
+ +
+ comment 18
+
+ +
+ + +
+
+
+ LibriVox recording of Dracula, by Bram Stoker. The classic vampire story by Bram Stoker revolves around a struggle between good and evil, tradition and modernity, and lust versus chastity. The author didn\'t invent vampires, but his novel has so captured the public\'s imagination that he is rightly considered their popularizer. Listen and you will meet not only the Count himself, but heroes Jonathan Harker and Abraham Van Helsing, plus an array of madmen, psychiatrists, and fair maidens who cross...
favoritefavoritefavorite ( 18 reviews )
Topics: librivox, audiobook, literature
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + William Walker Atkinson +
+
+ +
+
+ audio
+ +
+ eye 301,707 +
+ +
+ favorite 37
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of Memory: How to Develop, Train and Use It, by William Walker Atkinson. Read by Roger Melin. An in-depth series of chapters devoted to the use of our memory system; as the title suggests, how to develop our memory system, how to train it to improve it, and how to make the best use of it in our everyday lives, and to improve our positions in life. This is not intended to be a series of chapters to impress friends and colleagues, nor to play \'tricks\' on others, rather it is...
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, audiobook, self help, assistance, memorization, knowledge, self-help, subconscious,...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Victor Appleton +
+
+ +
+
+ audio
+ +
+ eye 18,498 +
+ +
+ favorite 2
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Tom Swift and His Motorcycle by Victor Appleton. Read by LibriVox Volunteers This is the very first Tom Swift adventure. Tom Swift has a newly purchased motorcycle, which he is modifying with his own inventions. He volunteers to use his bike to carry his father\'s new turbine design plans to Albany, testing his motorcycle enhancements at the same time. Set upon by corporate spies out to steal his dad\'s plans, Tom must escape from them, recover the plans, and complete his...
Topics: librivox, audiobooks, children, fiction, adventure, science fiction, young adult, tom swift, ya,...
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Frances Hodgson Burnett +
+
+ +
+
+ audio
+ +
+ eye 3.8M +
+ +
+ favorite 128
+ +
+ comment 5
+
+ +
+ + +
+
+
+ Librivox recording of The Secret Garden, by Frances Hodgson Burnett. Read by Kara Shallenberg Mary Lennox is a spoiled, middle-class, self-centred child who has been recently orphaned. She is accepted into the quiet and remote country house of an uncle, who has almost completely withdrawn into himself after the death of his wife. Mary gradually becomes drawn into the hidden side of the house: why does she hear the crying of a unseen child? Why is there an overgrown, walled garden, its door long...
favoritefavoritefavoritefavoritefavorite ( 5 reviews )
Topics: literature, audiobook, children, librivox
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + J. M. Barrie +
+
+ +
+
+ audio
+ +
+ eye 3.7M +
+ +
+ favorite 99
+ +
+ comment 2
+
+ +
+ + +
+
+
+ Librivox recording of Peter Pan by J. M. Barrie. Read by Librivox volunteers. Peter Pan is the well-loved story of three children and their adventures in Neverland with the boy who refuses to grow up. Swashbuckling, fairy dust, and flight; mermaid lagoons, ticking crocodiles, and Princess Tiger Lily; second to the right and then straight on till morning. You know the story... and if you don\'t, please start listening immediately! (summary by Meredith Hughes) For further information, including...
favoritefavoritefavoritefavoritefavorite ( 2 reviews )
Topics: librivox, audiobook, Peter Pan, James Matthew Barrie, children, fantasy, Neverland, Tinkerbell,...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Ernest Thompson Seton +
+
+ +
+
+ audio
+ +
+ eye 17,686 +
+ +
+ favorite 1
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Wild Animals At Home by Ernest Thompson Seton. Read in English by LibriVox volunteers. Wildlife artist Ernest Thompson Seton shares anecdotes of wild animals that he encountered in Yellowstone Park. "I have aimed to show something of the little aspects of the creatures\' lives, which are those that the ordinary traveller will see; I go with him indeed, pointing out my friends as they chance to pass, adding a few comments that should make for a better acquaintance on...
Topics: librivox, audiobooks, nature, animals, nonfiction, wildlife
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Roald Amundsen +
+
+ +
+
+ audio
+ +
+ eye 18,500 +
+ +
+ favorite 1
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of The North West Passage -The Gjöa Expedition 1903-1907 (Volume I) by Roald Amundsen. Read in English by Steven Seitel Roald Amundsen and six hearty seafarers tackle the North West Passage in search of the elusive wandering magnetic North Pole. (Summary by Steve Seitel) For further information, including links to online text, reader information, RSS feeds, CD cover or other formats (if available), please go to the LibriVox catalog page for this recording. For more free...
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, audiobooks, polar exploration, north west passage, roald amundsen
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Dion Boucicault +
+
+ +
+
+ audio
+ +
+ eye 17,326 +
+ +
+ favorite 1
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of London Assurance by Dion Boucicault. Read in English by LibriVox Volunteers. This fast-paced Victorian farce is at heart a comedy of manners. Dion Bouciault’s witty dialogue ridicules the pretensions of society as the plot sets up the unpleasant initial situation of the aging, vain Sir Harcourt Courtly being set by a special provision of her father’s will to marry 18-year-old Grace Harkaway. The situation quickly escalates upon their arrival at Oak Hall to seal the...
Topics: librivox, audiobooks, comedy, romance, farce, comedy of manners
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + LibriVox cover makers +
+
+ +
+
+ audio
+ +
+ eye 2.1M +
+ +
+ favorite 3
+ +
+ comment 0
+
+ +
+ + +
+
+
+ A thirty-sixth collection of CD cover art, created by volunteers for some of our LibriVox Audio Books.  We\'ll add more covers as our volunteers create them, so please check back. Each cover can be downloaded as a .pdf to print out and insert into a jewel case, or as a 300x300px .jpg for your iTunes Album Art. This is just one of many LibriVox cover art pages. You\'ll find a complete list on our top page .
Topics: Librivox, audiobook, cd cover, cd art
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + + + +
+
+ audio
+ +
+ eye 26,494 +
+ +
+ favorite 3
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Coffee Break Collection 30 - Mythical Creatures by Various. Read in English by Colleen McMahon; Michele Fry; Tony Scheinman; Piotr Nater; Joanna Michal Hoyt; Joanna Schreck; Sonia; Vincent Maraldo; Andrea Atwood; Newgatenovelist; Lewis West; Kayty Harrelson; Maddie Ruth This is the 30th Coffee Break Collection, in which Librivox readers select and read stories or poems, fiction or non-fiction pieces of fifteen minutes\' duration or less, suitable for short commutes and...
Topics: librivox, audiobooks
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Librivox cover makers +
+
+ +
+
+ audio
+ +
+ eye 6.3M +
+ +
+ favorite 27
+ +
+ comment 0
+
+ +
+ + +
+
+
+ A thirtyfifth collection of CD cover art, created by Availle for some of our LibriVox Audio Books.  We\'ll add more covers as our volunteers create them, so please check back. Each cover can be downloaded as a .pdf to print out and insert into a jewel case, or as a 300x300px .jpg for your iTunes Album Art. This is just one of many LibriVox cover art pages. You\'ll find a complete list on our top page .
Topics: librivox, audiobooks, cd covers, audiobook, cover art, album art
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Homer +
+
+ +
+
+ audio
+ +
+ eye 3.5M +
+ +
+ favorite 213
+ +
+ comment 5
+
+ +
+ + +
+
+
+ Librivox recording of The Odyssey , by Homer (transl. Samuel Butler). The Odyssey is one of the two major ancient Greek epic poems (the other being the Iliad ), attributed to the poet Homer. The poem is commonly dated to between 800 and 600 BC. The poem is, in part, a sequel to the Iliad , and concerns the events that befall the Greek hero Odysseus in his long journey back to his native land Ithaca after the fall of Troy. It takes Odysseus ten years to return to his native land of Ithaca after...
favoritefavoritefavoritefavorite ( 5 reviews )
Topics: LibriVox, literature, audiobook, homer, classics, adventure, poetry
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Various +
+
+ +
+
+ audio
+ +
+ eye 3.3M +
+ +
+ favorite 24
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of 1891 Collection by Various. Read by Bellona Times A look at the year 1891 through literature and non-fiction essays first published that year, including works by Mary E Wilkins, Sir Arthur Conan Doyle, Sara Orne Jewett, and Oscar Wilde. (Summary by BellonaTimes) For further information, including links to online text, reader information, RSS feeds, CD cover, M4B or other formats (if available), please go to the LibriVox catalog page for this recording. For more free audio...
Topics: Romance, mystery, commentary, Max O\'Rell, Arthur Conan Doyle, Sarah Orne Jewett, A J Payne, Edith...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + John Buchan +
+
+ +
+
+ audio
+ +
+ eye 15,787 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of The Thirty-Nine Steps (Version 2) by John Buchan. Read in English by Tom Haire. Richard Hannay thirsts for adventure. Down and out in early retirement in South London, Hannay bores of the easy life. When Franklin Scudder reveals a secret ploy to set all of Europe to arms, Hannay finds his cure. With experience, intelligence, and a good deal of luck, Richard Hannay peels the layers one step at a time. (Summary by Tom Haire) For further information, including links to online...
Topics: librivox, audiobooks
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Lewis Carroll +
+
+ +
+
+ audio
+ +
+ eye 3.1M +
+ +
+ favorite 130
+ +
+ comment 2
+
+ +
+ + +
+
+
+ LibriVox recording of Alice\'s Adventures in Wonderland, by Lewis Carroll. Read by Kara Shallenberg. Alice\'s Adventures in Wonderland tells the story of a girl named Alice who falls down a rabbit hole into a fantasy world populated by peculiar and anthropomorphic creatures. The tale plays with logic in ways that have given the story lasting popularity with adults as well as children. It is considered to be one of the most characteristic examples of the "literary nonsense" genre, and...
favoritefavoritefavoritefavoritefavorite ( 2 reviews )
Topics: librivox, audiobooks, children, fantasy, adventure, carroll, fiction
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + + + +
+
+ audio
+ +
+ eye 15,284 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Across Mongolian Plains: A Naturalist\'s Account of China\'s \'Great Northwest\' by Roy Chapman Andrews. Read in English by volunteer readers. An account of a 1918 journey to Northern China by famed adventurer/paleontologist Roy Chapman Andrews. Andrews, who was the inspiration for the many explorer hero characters (including Indiana Jones), wrote this book for the general public, excluding "scientific details" that they might find "wearisome". - Summary by...
Topics: librivox, audiobooks, culture, travel, adventure, animals, Hunting, memoir, china, mongolia
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Franz Kafka +
+
+ +
+
+ audio
+ +
+ eye 738,641 +
+ +
+ favorite 113
+ +
+ comment 5
+
+ +
+ + +
+
+
+ Librivox recording of The Metamorphosis by Franz Kafka, translated by Ian Johnston. Read by David Barnes The Metamorphosis (in German, Die Verwandlung, "The Transformation") is a novella by Franz Kafka, first published in 1915, and arguably the most famous of his works along with the longer works The Trial and The Castle. The story begins with a traveling salesman, Gregor Samsa, waking to find himself transformed into a giant "monstrous vermin". (Summary from Wikipedia). For...
favoritefavoritefavoritefavoritefavorite ( 5 reviews )
Topics: librivox, audiobook, literature, kafka, metamorphosis, verwandlung, samsa
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Frances Hodgson Burnett +
+
+ +
+
+ audio
+ +
+ eye 1.5M +
+ +
+ favorite 47
+ +
+ comment 13
+
+ +
+ + +
+
+
+ LibriVox recording of A Little Princess, by Frances Hodgson Burnett. Read by Karen Savage. Sara is brought to Miss Minchin\'s Select Seminary for Young Ladies by her father, Captain Crewe, because the climate in India doesn\'t agree with children. This is the story of her time at Miss Minchin\'s. (Summary by Karen Savage) For further information, including links to online text, reader information, RSS feeds, CD cover or other formats (if available), please go to the LibriVox catalog page for this...
favoritefavoritefavoritefavorite ( 13 reviews )
Topics: librivox, literature, audiobook, children, boarding school
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Charles Dickens +
+
+ +
+
+ audio
+ +
+ eye 2.4M +
+ +
+ favorite 52
+ +
+ comment 1
+
+ +
+ + +
+
+
+ Librivox recording of the Bleak House by Charles Dickens. Read by Cynthia Lyons. Bleak House is the ninth novel by Charles Dickens, published in 20 monthly parts between March 1852 and September 1853. It is widely held to be one of Dickens’ finest and most complete novels, containing one of the most vast, complex and engaging arrays of minor characters and sub-plots in his entire canon. Dickens tells all of these both through the narrative of the novel’s heroine, Esther Summerson, and as an...
favoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, literature, audiobook, Bleak House, Charles Dickens, Esther Summerson, Tulkinghorn, John...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sir Arthur Conan Doyle +
+
+ +
+
+ audio
+ +
+ eye 3.1M +
+ +
+ favorite 68
+ +
+ comment 5
+
+ +
+ + +
+
+
+ LibriVox recording of The Adventures of Sherlock Holmes , by Sir Arthur Conan Doyle. Read by Ruth Golding . A collection of twelve short stories featuring Conan Doyle\'s legendary detective, originally published as single stories in Strand Magazine and subsequently collected into a single volume. There is not always a crime committed nor a culprit to find, and when there is, Holmes does not invariably get his man. However, his extraordinary powers of deduction generally solve the mystery, often...
favoritefavoritefavoritefavoritefavorite ( 5 reviews )
Topics: librivox, audio book, mystery, sherlock holmes, crime, detective, short stories
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + cover makers +
+
+ +
+
+ audio
+ +
+ eye 6.9M +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ Images for LV projects 02
Topic: images thumb nails
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jane Austen +
+
+ +
+
+ audio
+ +
+ eye 3.5M +
+ +
+ favorite 67
+ +
+ comment 9
+
+ +
+ + +
+
+
+ LibriVox recording of Pride and Prejudice , by Jane Austen. Read by Elizabeth Klett. Pride and Prejudice is Jane Austen\'s classic comic romance, in which the five Bennett sisters try to find that most elusive creature: a single man in possession of a large fortune. Sparks fly when sweet, pretty Jane meets their new neighbor, Mr. Bingley, but her sister Elizabeth is most offended by his haughty friend, Mr. Darcy. This is Austen at the height of her powers: the ironic narration, hilariously drawn...
favoritefavoritefavoritefavoritefavorite ( 9 reviews )
Topics: librivox, audio, austen, pride, prejudice, literature, romance
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Honore de Balzac +
+
+ +
+
+ audio
+ +
+ eye 2.1M +
+ +
+ favorite 13
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Letters of Two Brides, by Honore de Balzac. Letters of Two Brides is an epistolary novel. The two brides are Louise de Chaulieu (Madame Gaston) and Renée de Maucombe (Madame l\'Estorade). The women became friends during their education at a convent and upon leaving began a life-long correspondence. For a 17 year period, they exchange letters describing their lives. Michelle Crandall reads Renee\'s letters, and Kara Shallenberg reads Louise\'s. Letters from the men in their...
Topics: librivox, literature, audiobooks, epistolary, letters, balzac
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Anatole France +
+
+ +
+
+ audio
+ +
+ eye 2.1M +
+ +
+ favorite 21
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of Penguin Island, by Anatole France. Read by Michael Sirois. This novel (original French title -- L\'Île des Pingouins) is a satire on human nature. The first publication was in 1908. These penguins are mistaken for humans by the 97-year-old priest, Father Mael, because of his bad eyesight. He baptizes them, and once baptized, they have no choice but to become human. They take on human traits (build civilizations, go to war, etc.). The book is very funny and powerful....
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: LibriVox, literature, audiobook, satire
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Cover makers +
+
+ +
+
+ audio
+ +
+ eye 6M +
+ +
+ favorite 4
+ +
+ comment 0
+
+ +
+ + +
+
+
+ Images for LV projects 01
Topic: images thumb nails
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Ayn Rand +
+
+ +
+
+ audio
+ +
+ eye 2.5M +
+ +
+ favorite 65
+ +
+ comment 5
+
+ +
+ + +
+
+
+ LibriVox\'s Anthem by Ayn Rand. Read by Chere Theriot. Anthem is a dystopic science fiction story taking place at some unspecified future date. Mankind has entered another dark age as a result of what Rand saw as the weaknesses of socialistic thinking and economics. Technological advancement is now carefully planned (when it is allowed to occur, if at all) and the concept of individuality has been eliminated (for example, the word "I" has disappeared from the language). As is common in...
favoritefavoritefavoritefavorite ( 5 reviews )
Topics: librivox, audiobooks, literature, philosophy, science fiction
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Thomas Hood +
+
+ +
+
+ audio
+ +
+ eye 11,681 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox  volunteers bring you 13 recordings of The Wee Man - A Romance by Thomas Hood. This was the Fortnightly Poetry project for March 7, 2021. Read in English by Andrea Atwood; Bruce Kachuk; ChadH94; czandra; Garth Burton; Graham Scott; holtonhj64 ; Larry Wilson; LeeSalter; mleigh; nbvoices; Phil Schempf and yaumixx. Thomas Hood was an English poet, author and humorist, best known for poems such as "The Bridge of Sighs" and "The Song of the Shirt". Hood wrote regularly...
Topics: librivox, audiobooks, literature, poetry, humor, nautical
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + William Makepeace Thackeray +
+
+ +
+
+ audio
+ +
+ eye 18,596 +
+ +
+ favorite 3
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of Our Street by William Makepeace Thackeray. Read in English by Kristina Rothe Written as an autobiographical sketch of a Mr. M.A. Titmarsh, Our Street is a tongue-in-cheek look at English society and the characters who live in the street where he finds himself. It is the second of five "Christmas Books" written by Thackeray under the pseudonym of M.A. Titmarsh. For further information, including links to online text, reader information, RSS feeds, CD cover or...
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, audiobooks, society, observation
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+
+
+ +
+
+ image
+ +
+ eye 7.1M +
+ +
+ favorite 13
+ +
+ comment 0
+
+ +
+ + +
+
+
+ images used for items in collection
Topic: librivox
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + H. G. Wells +
+
+ +
+
+ audio
+ +
+ eye 1.8M +
+ +
+ favorite 71
+ +
+ comment 2
+
+ +
+ + +
+
+
+ LibriVox recording of The Time Machine, by H.G. Wells. Read by Mark Nelson. H.G. Wells\' classic science fiction-fantasy story, in which a scientist known only as “The Time Traveller” tells the tale of his journey to the year 802,701 A.D. and beyond, where he witnesses the end of human civilization as we know it, as well as the beginning of the end of the world. This original time-travel story has been copied many times, but never improved upon. (Summary by Mark Nelson) For further...
favoritefavoritefavoritefavoritefavorite ( 2 reviews )
Topics: librivox, literature, audiobook, adventure, fantasy, fiction, science fiction, teen/young adult
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Robert Louis Stevenson +
+
+ +
+
+ audio
+ +
+ eye 3.8M +
+ +
+ favorite 173
+ +
+ comment 22
+
+ +
+ + +
+
+
+ Librivox recording of Treasure Island by Robert Louis Stevenson. Read by Adrian Praetzellis. A mysterious map, pirates, and pieces of eight! When young Jim Hawkins finds a map to pirates’ gold he starts on an adventure that takes him from his English village to a desert island with the murderous Black Dog, half-mad Ben Gunn, and (of course) Long John Silver. Arr Jim lad! R.L. Stevenson (1850-1894) was born in Scotland and travelled extensively in California and the south Pacific. (Summary by...
favoritefavoritefavoritefavoritefavorite ( 22 reviews )
Topics: librivox, audiobooks, pirates, Stevenson, treasure, children\'s literature
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Max Beerbohm +
+
+ +
+
+ audio
+ +
+ eye 25,607 +
+ +
+ favorite 2
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of Zuleika Dobson, by Max Beerbohm. Read by Termin Dyan. \'A wickedly funny 1911 satire on undergraduate life in Edwardian Oxford\' in which the entire student body of Oxford university including the young, handsome aristocrat the Duke of Dorset falls hopelessly in love with Zuleika who is visiting her grandfather, the warden of Judas college, and ultimately commit mass suicide at the end of \'Eights Week\' (Summary by Andy Minter) For further information, including links to...
favoritefavoritefavoritefavorite ( 1 reviews )
Topics: audiobook, librivox, satire, oxford, suicide
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sir Arthur Conan Doyle +
+
+ +
+
+ audio
+ +
+ eye 3.2M +
+ +
+ favorite 70
+ +
+ comment 3
+
+ +
+ + +
+
+
+ LibriVox recording of The Memoirs of Sherlock Holmes, by Sir Arthur Conan Doyle. Sherlock Holmes is a fictional detective of the late 19th and early 20th centuries, who first appeared in publication in 1887. He was devised by Scottish author and doctor Sir Arthur Conan Doyle. A brilliant London-based detective, Holmes is famous for his prowess at using logic and astute observation to solve cases. He is perhaps the most famous fictional detective, and indeed one of the best known and most...
favoritefavoritefavorite ( 3 reviews )
Topics: librivox, audiobook, literature, adventure, mystery, doyle, sherlock holmes
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Ivan Turgenev trans. Constance Garnett +
+
+ +
+
+ audio
+ +
+ eye 587,762 +
+ +
+ favorite 13
+ +
+ comment 3
+
+ +
+ + +
+
+
+ LibriVox recording of First Love, by Ivan Turgenev, translated by Constance Garnett. Read by Martin Geeson. The title of the novella is almost an adequate summary in itself. The "boy-meets-girl-then-loses-her" story is universal but not, I think, banal - despite a surprise ending which notoriously turns out to be very little of a surprise. First Love is given its originality and poignancy by Turgenev\'s mastery of the piercing turning-point (akin to Joyce\'s "epiphanies") that...
favoritefavoritefavoritefavoritefavorite ( 3 reviews )
Topics: librivox, audiobook, literature, love, romance, novella
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Charlotte Brontë +
+
+ +
+
+ audio
+ +
+ eye 3.3M +
+ +
+ favorite 92
+ +
+ comment 21
+
+ +
+ + +
+
+
+ LibriVox recording of Jane Eyre, by Charlotte Brontë. Read by Elizabeth Klett. Charlotte Bronte\'s classic novel Jane Eyre is narrated by the title character, an orphan who survives neglect and abuse to become a governess at the remote Thornfield Hall. She finds a kindred spirit in her employer, the mysterious and brooding Mr. Rochester, but he hides a terrible secret that threatens their chances of happiness. (Summary by Elizabeth Klett) For further information, including links to online text,...
favoritefavoritefavoritefavoritefavorite ( 21 reviews )
Topics: librivox, audiobook, classic, romance
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + P.G. Wodehouse +
+
+ +
+
+ audio
+ +
+ eye 938,415 +
+ +
+ favorite 17
+ +
+ comment 5
+
+ +
+ + +
+
+
+ LibriVox recording of The Girl on the Boat, by P.G. Wodehouse. Read by Kara Shallenberg . Also published as "Three Men and a Maid". The maid of the title is red-haired, dog-loving Wilhelmina "Billie" Bennet, and the three men are Bream Mortimer, a long-time friend and admirer of Billie, Eustace Hignett, a lily-livered poet who is engaged to Billie at the opening of the tale, and Sam Marlowe, Eustace\'s dashing cousin, who falls for Billie at first sight. All four find...
favoritefavoritefavoritefavoritefavorite ( 5 reviews )
Topics: librivox, audiobook, fiction, humor, romance, teen, young adult, comedy, P.G. Wodehouse, Three Men...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jane Austen +
+
+ +
+
+ audio
+ +
+ eye 3.7M +
+ +
+ favorite 91
+ +
+ comment 2
+
+ +
+ + +
+
+
+ LibriVox recording of Emma, by Jane Austen. Read by Sherry Crowther. (Vol. 1 Ch. 4 and Vol. 2 Ch. 11 read by Kara Shallenberg) Sherry reads Jane Austen’s sparkling comedy of manners with wit and vivacity, and brings the characters to life. Mr. Woodhouse worries and frets, Miss Bates chatters on, and Emma blithely manipulates and misunderstands her friends and family until she finally learns her lesson! (Summary by Kara) For further information, including links to online text, reader...
favoritefavoritefavoritefavorite ( 2 reviews )
Topics: librivox, literature, audiobook, austen, emma, comedy, regency, england
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + William Shakespeare +
+
+ +
+
+ audio
+ +
+ eye 1.8M +
+ +
+ favorite 19
+ +
+ comment 0
+
+ +
+ + +
+
+
+ Librivox recording of Romeo and Juliet by William Shakespeare. Read by Sam Stinson . Romeo and Juliet is an early tragedy by William Shakespeare about two teenage "star-cross\'d lovers" whose "untimely deaths" ultimately unite their feuding households. The play has been highly praised by literary critics for its language and dramatic effect. It was among Shakespeare\'s most popular plays during his lifetime and, along with Hamlet, is one of his most frequently performed plays....
Topics: librivox, literature, audiobook, William Shakespeare, Romeo, Juliet, drama, play, tragedy, tragic...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sir Arthur Conan Doyle +
+
+ +
+
+ audio
+ +
+ eye 1.4M +
+ +
+ favorite 60
+ +
+ comment 1
+
+ +
+ + +
+
+
+ LibriVox recording of The Adventures of Sherlock Holmes (version 4) by Sir Arthur Conan Doyle. Read in English by David Clarke The Adventures of Sherlock Holmes is a collection of 12 short stories that were originally illustrated by Sidney Paget. These are the first set of short stories that were published and followed the publishing of his first 2 novels, A Study in Scarlet and The Sign of the Four. - Summary by David Clarke For further information, including links to online text, reader...
favoritefavoritefavoritefavoritefavorite ( 1 reviews )
Topics: librivox, audiobooks, Sherlock Holmes, Detective, Crime
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + + + +
+
+ audio
+ +
+ eye 16,049 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of Beneath the Banner: Being Narratives of Noble Lives and Brave Deeds by Frederick J. Cross. Read in English by Lynda Marie Neilson. In this book are over 30 stories by various people about men and women who have done extraordinary things during and often before the time when similar products were invented. It is suitable for bedtime reading. Summary by Lynda Marie Neilson For further information, including links to online text, reader information, RSS feeds, CD cover or...
Topics: librivox, audiobooks, invention
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jacob & Wilhelm Grimm +
+
+ +
+
+ audio
+ +
+ eye 2.6M +
+ +
+ favorite 102
+ +
+ comment 2
+
+ +
+ + +
+
+
+ LibriVox recording of Grimm\'s Fairy Tales (version 2), by Jacob & Wilhelm Grimm. Read by Bob Neufeld. Children\'s and Household Tales (German: Kinder- und Hausmärchen) is a collection of German origin fairy tales first published in 1812 by Jacob and Wilhelm Grimm, the Brothers Grimm. The collection is commonly known today as Grimms\' Fairy Tales (German: Grimms Märchen). ( Summary by Wikipedia ) For further information, including links to online text, reader information, RSS feeds, CD cover...
favoritefavoritefavoritefavoritefavorite ( 2 reviews )
Topics: librivox, audiobook, children, fairy tales, fiction, short stories, Grimm, Grimms\' Fairy Tales
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + David Marshall Brooks +
+
+ +
+
+ audio
+ +
+ eye 172,972 +
+ +
+ favorite 13
+ +
+ comment 2
+
+ +
+ + +
+
+
+ LibriVox recording of The Necessity of Atheism by David Marshall Brooks. Read by Wesseling Plain speaking is necessary in any discussion of religion, for if the freethinker attacks the religious dogmas with hesitation, the orthodox believer assumes that it is with regret that the freethinker would remove the crutch that supports the orthodox. And all religious beliefs are "crutches" hindering the free locomotive efforts of an advancing humanity. There are no problems related to human...
favoritefavoritefavorite ( 2 reviews )
Topics: librivox, audiobooks, nonfiction, atheism, humanism, religion, freethinkers, spirituality, church,...
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + + + +
+
+ audio
+ +
+ eye 2.9M +
+ +
+ favorite 65
+ +
+ comment 3
+
+ +
+ + +
+
+
+ LibriVox recording of Robinson Crusoe by Daniel Defoe. Read by Denny Sayers. Daniel Defoe\'s The Life and Strange Surprizing Adventures of Robinson Crusoe of York, Mariner (1719) is considered by many the first English novel. Based on the real-life experiences of the castaway Alexander Selkirk, the book has had a perrenial appeal among readers of all ages - especially the young adult reading public - who continue to find inspiration in the inventive resourcefulness of its hero, sole survivor of...
favoritefavoritefavoritefavoritefavorite ( 3 reviews )
Topics: librivox, literature, audiobook, adventure
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jean Macé +
+
+ +
+
+ audio
+ +
+ eye 14,892 +
+ +
+ favorite 1
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of La Grammaire de Mademoiselle Lili by Jean Macé. Read in French by Ezwa. Les rudiments de la grammaire française, art de parler et d\'écrire correctement dans la langue de Molière, sont ici mis à la portée d\'une petite fille. French grammar or the art of speaking and writing in that language, made very plain to a little girl. - Summary by Ezwa For further information, including links to online text, reader information, RSS feeds, CD cover or other formats (if...
Topics: librivox, audiobooks, French, français, grammar, enfants, grammaire française
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Sir Arthur Conan Doyle +
+
+ +
+
+ audio
+ +
+ eye 3M +
+ +
+ favorite 106
+ +
+ comment 2
+
+ +
+ + +
+
+
+ LibriVox recording of The Return of Sherlock Holmes, by Sir Arthur Conan Doyle. Having left Sherlock Holmes apparently deceased at the conclusion of The Final Problem (in The Memoirs of Sherlock Holmes), we now find that he is alive after all! In this collection, first published in 1905, the great detective causes Watson to faint (The Empty House), demonstrates that cryptography is elementary (The Dancing Men), and gets engaged (Charles Augustus Milverton). Join in the fun as Holmes deduces his...
favoritefavoritefavoritefavoritefavorite ( 2 reviews )
Topics: librivox, literature, audiobooks, mystery, detective, holmes, doyle, short story
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + LV covermakers +
+
+ +
+
+ audio
+ +
+ eye 3.6M +
+ +
+ favorite 2
+ +
+ comment 0
+
+ +
+ + +
+
+
+ Thumb images for LibriVox Projects
Topic: cover images
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + William Shakespeare +
+
+ +
+
+ audio
+ +
+ eye 2.5M +
+ +
+ favorite 61
+ +
+ comment 0
+
+ +
+ + +
+
+
+ Librivox recording of Romeo and Juliet, by William Shakespeare. Read by Becky Crackel. Romeo and Juliet is perhaps the most famous of Shakespeare\'s plays and is thought to be the most famous love story in Western history. It concerns the fate of two very young lovers who would do anything to be together. The Montagues and the Capulets of Verona, Italy, are in the midst of a long-standing feud when Romeo Montague drops in on a masquerade party at the Capulets\'. While there he meets and woos the...
Topics: librivox, audiobook, drama
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Charles Dickens +
+
+ +
+
+ audio
+ +
+ eye 3.8M +
+ +
+ favorite 158
+ +
+ comment 6
+
+ +
+ + +
+
+
+ LibriVox recording of A Tale of Two Cities, by Charles Dickens. A Tale of Two Cities (1859) is a historical novel by Charles Dickens; it is moreover a moral novel strongly concerned with themes of guilt, shame, redemption and patriotism. The plot centers on the years leading up to French Revolution and culminates in the Jacobin Reign of Terror. It tells the story of two men, Charles Darnay and Sydney Carton, who look very alike but are entirely different in character. (Summary from wikipedia)...
favoritefavoritefavorite ( 6 reviews )
Topics: librivox, audiobook, literature, dickens
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
Librivoxaudio Covers
+
+
+ + +
+ + +
+ + + + + + +
+
+ audio
+ +
+ eye 3.4M +
+ +
+ favorite 14
+ +
+ comment 0
+
+ +
+ + +
+
+
+ A thirty-fourth collection of CD cover art, created by volunteers for some of our LibriVox Audio Books. We\'ll add more covers as our volunteers create them, so please check back. Each cover can be downloaded as a .pdf to print out and insert into a jewel case, or as a 300x300px .jpg for your iTunes Album Art. Each thumbnail is linked to the catalog page where the links to the cover files can be found. This is just one of many LibriVox cover art pages. You\'ll find a complete list on our top page...
Topics: librivox, audiobook, cover art, album art
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Harriet Beecher Stowe +
+
+ +
+
+ audio
+ +
+ eye 3.9M +
+ +
+ favorite 175
+ +
+ comment 13
+
+ +
+ + +
+
+
+ Librivox recording of Uncle Tom\'s Cabin by Harriet Beecher Stowe. Read by John Greenman. Among the most "banned" books in the United States, Uncle Tom’s Cabin; or, Life Among the Lowly is a novel by American author Harriet Beecher Stowe which treats slavery as a central theme. Stowe was a Connecticut-born teacher at the Hartford Female Academy and an active abolitionist. The novel is believed to have had a profound effect on the North’s view of slavery. In fact, when he met...
favoritefavoritefavoritefavoritefavorite ( 13 reviews )
Topics: librivox, audiobook, literature, stowe, uncle tom
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jane Austen +
+
+ +
+
+ audio
+ +
+ eye 4.6M +
+ +
+ favorite 34
+ +
+ comment 5
+
+ +
+ + +
+
+
+ Librivox recording of Pride and Prejudice, by Jane Austen. Read by Annie Coleman . Jane Austen\'s classic novel chronicles the events in the lives of the Bennet family. Take a family with five unmarried daughters and a lack of wealth, throw in a new wealthy neighbor or two, plus a whole regiment of soldiers in town, and add a heaping spoonful of pride and a pinch of prejudice. Mix it all together and you get a story full of tears and laughter, embarrassment and pride, and, of course, love....
favoritefavoritefavoritefavoritefavorite ( 5 reviews )
Topics: librivox, audiobook, literature
Source: http://www.gutenberg.org/etext/1342
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Charles Dickens +
+
+ +
+
+ audio
+ +
+ eye 3.1M +
+ +
+ favorite 137
+ +
+ comment 8
+
+ +
+ + +
+
+
+ This is a LibriVox recording of Great Expectations, read by Mark F. Smith. This classic tale tells of an orphan, Pip, who through a series of strange circumstances first finds a trade as a blacksmith\'s apprentice and then learns that he has "great expectations" of a future inheritance from an anonymous benefactor. He soon learns to live the profligate life of a gentleman as he gradually sheds his associations with the gentle souls of his past, Joe (the blacksmith) and Biddy (a...
favoritefavoritefavoritefavoritefavorite ( 8 reviews )
Topics: Audiobook, LibriVox, Fiction, England
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + William Tyndale +
+
+ +
+
+ audio
+ +
+ eye 8,691 +
+ +
+ favorite 0
+ +
+ comment 0
+
+ +
+ + +
+
+
+ LibriVox recording of The Obedience of a Christian Man by William Tyndale. Read in English by David Ronald "The obedience of a Christian man" begins by contrasting the life of a true Christian to those holding high positions within the Romish Church. A scathing attack against the Popes, Cardinals and Bishops living in luxury, who also refrain from teaching Scripture and would rather attach themselves to "Doctors" who often contradict themselves. Tyndale compares these men to...
Topics: librivox, audiobooks, Christianity, church history, Reformation, reformers
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jane Austen +
+
+ +
+
+ audio
+ +
+ eye 5.8M +
+ +
+ favorite 151
+ +
+ comment 17
+
+ +
+ + +
+
+
+ LibriVox recording of Pride and Prejudice by Jane Austen. Read by Karen Savage. Pride and Prejudice is the most famous of Jane Austen’s novels, and its opening is one of the most famous lines in English literature - “It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.” Its manuscript was first written between 1796 and 1797, and was initially called First Impressions, but was never published under that title. Following...
favoritefavoritefavoritefavorite ( 17 reviews )
Topics: librivox, literature, audiobook, austen, romance, humour
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Jacob Abbott +
+
+ +
+
+ audio
+ +
+ eye 1.9M +
+ +
+ favorite 63
+ +
+ comment 4
+
+ +
+ + +
+
+
+ Alexander the Great was one of the most successful military commanders in history, and was undefeated in battle. By the time of his death, he had conquered most of the world known to the ancient Greeks. Alexander the Great is one of many biographies aimed at young people written by Jacob Abbott and his brother. The biographies are written in such a way that makes them appealing and easily accessible to everyone. - Written by Wikipedia and Lizzie Driver For further information, including links...
favoritefavoritefavoritefavorite ( 4 reviews )
Topics: librivox, literature, audiobook, History, biography, alexander
Source: Librivox recording of a public-domain text
+
+
+ + + +
+ + +
+
+
The LibriVox Free Audiobook Collection
+
+
+ + +
+ + +
+ + + + +
+ +
+ + +
+
+ by + Mark Twain +
+
+ +
+
+ audio
+ +
+ eye 3.9M +
+ +
+ favorite 65
+ +
+ comment 8
+
+ +
+ + +
+
+
+ LibriVox recording of The Adventures of Huckleberry Finn (version 02). Read by Mark F. Smith. In The Adventures of Huckleberry Finn, Mark Twain creates an entertaining adventure of Middle America in the 1800\'s - afloat on a raft on the Mississippi River. Huck escapes his civilized life when he arranges his own "murder" and turns back into the backwoods, downriver yokel he started as, and in the process springing a slave, Jim, from bondage. Huck and Jim experience life as a series of...
favoritefavoritefavoritefavorite ( 8 reviews )
Topics: librivox, literature, audiobooks, twain, adventure, satire, finn, humor
Source: Librivox recording of a public-domain text
+
+
+ +
+
+
+ +
+
+ + +
+
+ + + + + + + +
+ + + +
+ + +
+ + + + + + + + + + + + + ' +]; diff --git a/tests/cache/backend.deviantart.com.oembed.570007402326b42f53bba131439de098.php b/tests/cache/backend.deviantart.com.oembed.570007402326b42f53bba131439de098.php new file mode 100644 index 00000000..6f3ec053 --- /dev/null +++ b/tests/cache/backend.deviantart.com.oembed.570007402326b42f53bba131439de098.php @@ -0,0 +1,69 @@ + [ + 'server' => [ + 'CloudFront', + 'Apache' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:44 GMT', + 'Mon, 10 Jun 2024 15:58:45 GMT' + ], + 'content-type' => [ + 'text/html', + 'application/json; charset=utf-8' + ], + 'content-length' => [ + '167', + '1122' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://backend.deviantart.com/oembed?url=https%3A%2F%2Fwww.deviantart.com%2Fsakimichan%2Fart%2FMisty-510056679&format=json' + ], + 'x-cache' => [ + 'Redirect from cloudfront', + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 14f5976b438d8329cf38c45f416655a6.cloudfront.net (CloudFront)', + '1.1 52923a8d354a8b3a1b839b39ec3a8ae6.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD53-P3', + 'MAD53-P3' + ], + 'x-amz-cf-id' => [ + 'VGBJ-jjqT2kEd8d-nKTOp-g_jT0kr-G3rT7CtF_8CJ8XZxTzaIElzA== HTTP/2 200', + 'dnbRWhAKi9epWnqYYxnVhf1YYK9_qnGd6zKBMuSFPgdkNsFDl8C_Cg==' + ], + 'cache-control' => [ + 'max-age=180' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:01:45 GMT' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-backend' => [ + 'web_http_back' + ], + 'Content-Location' => [ + 'https://backend.deviantart.com/oembed?url=https%3A%2F%2Fwww.deviantart.com%2Fsakimichan%2Fart%2FMisty-510056679&format=json' + ], + 'X-Request-Time' => [ + '0.610 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"photo","title":"Misty","category":"Fan Art > Digital Art > Drawings > Games","url":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51\\/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzlhZDhmYmM4LWFlZTgtNGU5Mi1hMDRiLTZhYmY3YTAzNmE1MVwvZDhmb2E5My04ZTFmYWRlOS0xODUzLTQ2NDQtYWY4Mi0yZWMyMTU5MGJmOTQuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0._JiXuDZWqsoAgateXxPBaC3_EPfHdri7pJCeKFhXnjA","author_name":"sakimichan","author_url":"https:\\/\\/www.deviantart.com\\/sakimichan","provider_name":"DeviantArt","provider_url":"https:\\/\\/www.deviantart.com","safety":"nonadult","pubdate":"2015-01-27T16:55:07-08:00","community":{"statistics":{"_attributes":{"views":386632,"favorites":22702,"comments":675,"downloads":0}}},"copyright":{"_attributes":{"url":"https:\\/\\/www.deviantart.com\\/sakimichan","year":"2015","entity":"sakimichan"}},"width":"695","height":"900","imagetype":"jpg","thumbnail_url":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51\\/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg\\/v1\\/fit\\/w_300,h_900,q_70,strp\\/misty_by_sakimichan_d8foa93-300w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM","thumbnail_width":300,"thumbnail_height":388,"thumbnail_url_150":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51\\/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg\\/v1\\/fit\\/w_150,h_150,q_70,strp\\/misty_by_sakimichan_d8foa93-150.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM","thumbnail_url_200h":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51\\/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg\\/v1\\/crop\\/w_154,h_200,x_0,y_0,scl_0.22302158273381,q_70,strp\\/misty_by_sakimichan_d8foa93-200h.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM","thumbnail_width_200h":154,"thumbnail_height_200h":200}' +]; diff --git a/tests/cache/backend.deviantart.com.oembed.66b9a9847160259b92cb282e88b008b5.php b/tests/cache/backend.deviantart.com.oembed.66b9a9847160259b92cb282e88b008b5.php new file mode 100644 index 00000000..02694505 --- /dev/null +++ b/tests/cache/backend.deviantart.com.oembed.66b9a9847160259b92cb282e88b008b5.php @@ -0,0 +1,43 @@ + [ + 'content-type' => [ + 'text/html; charset=ISO-8859-1' + ], + 'content-length' => [ + '186' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:24:40 GMT' + ], + 'server' => [ + 'Apache' + ], + 'x-backend' => [ + 'web_http_back' + ], + 'x-cache' => [ + 'Error from cloudfront' + ], + 'via' => [ + '1.1 7cd2262b9bb2f116de2e74d9d97ab5d1.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'WAW50-C1' + ], + 'x-amz-cf-id' => [ + '7S-Qry3tlMeaLRy07t4EyMw0ZWv8Zxi_cuJoZ3M1vK9bXl7AiiplwQ==' + ], + 'Content-Location' => [ + 'https://backend.deviantart.com/oembed?url=https%253A%252F%252Fwww.deviantart.com%252Fsakimichan%252Fart%252FMisty-510056679&format=json' + ], + 'X-Request-Time' => [ + '0.952 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => '404 Not Found (https%3A%2F%2Fwww.deviantart.com%2Fsakimichan%2Fart%2FMisty-510056679) The URL https%3A%2F%2Fwww.deviantart.com%2Fsakimichan%2Fart%2FMisty-510056679 is not a deviation URL' +]; diff --git a/tests/cache/backend.deviantart.com.oembed.7f37b90b172a0cec6c623a4a2b9b9ce0.php b/tests/cache/backend.deviantart.com.oembed.7f37b90b172a0cec6c623a4a2b9b9ce0.php new file mode 100644 index 00000000..e9103392 --- /dev/null +++ b/tests/cache/backend.deviantart.com.oembed.7f37b90b172a0cec6c623a4a2b9b9ce0.php @@ -0,0 +1,69 @@ + [ + 'server' => [ + 'CloudFront', + 'Apache' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:46 GMT', + 'Mon, 10 Jun 2024 15:58:47 GMT' + ], + 'content-type' => [ + 'text/html', + 'application/json; charset=utf-8' + ], + 'content-length' => [ + '167', + '1118' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://backend.deviantart.com/oembed?url=https%3A%2F%2Fwww.deviantart.com%2Fpachunka%2Fart%2FCope-145564099&format=json' + ], + 'x-cache' => [ + 'Redirect from cloudfront', + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 881a5a546bfcb1f1b6d589576d5ee9f6.cloudfront.net (CloudFront)', + '1.1 ce4d5cfcd9ad826e9d9eb4efddff685c.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD53-P3', + 'MAD53-P3' + ], + 'x-amz-cf-id' => [ + 'M9uMKvcDEnERf49tY6Tq7H3xmCxS1d0B7s6MlgRUlfVjMchmm0ygPA== HTTP/2 200', + 'cypBlSE3B0WGBIqcaMjK2eZYggX5b7de4Cv1zDMPMNEaHX9qrfVNOw==' + ], + 'cache-control' => [ + 'max-age=180' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:01:47 GMT' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-backend' => [ + 'web_http_back' + ], + 'Content-Location' => [ + 'https://backend.deviantart.com/oembed?url=https%3A%2F%2Fwww.deviantart.com%2Fpachunka%2Fart%2FCope-145564099&format=json' + ], + 'X-Request-Time' => [ + '0.891 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"photo","title":"Cope","category":"Digital Art > Drawings & Paintings > Illustrations > Conceptual","url":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/2b5a457d-dde7-459a-badf-774e8e506025\\/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzJiNWE0NTdkLWRkZTctNDU5YS1iYWRmLTc3NGU4ZTUwNjAyNVwvZDJlbnh6Ny00MzFjYTljMy05ODdmLTRiMmQtYWU2YS1jYmJkZDFjMGUyYmYuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.pCEF4M_tMVZI92ZKClZdcMu5UqpQ3131DrHsx1WxefY","author_name":"pachunka","author_url":"https:\\/\\/www.deviantart.com\\/pachunka","provider_name":"DeviantArt","provider_url":"https:\\/\\/www.deviantart.com","safety":"nonadult","pubdate":"2009-12-02T23:59:51-08:00","community":{"statistics":{"_attributes":{"views":3279,"favorites":10,"comments":5,"downloads":63}}},"copyright":{"_attributes":{"url":"https:\\/\\/www.deviantart.com\\/pachunka","year":"2009","entity":"pachunka"}},"width":"448","height":"672","imagetype":"jpg","thumbnail_url":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/2b5a457d-dde7-459a-badf-774e8e506025\\/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg\\/v1\\/fit\\/w_300,h_672,q_70,strp\\/cope_by_pachunka_d2enxz7-300w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8","thumbnail_width":300,"thumbnail_height":450,"thumbnail_url_150":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/2b5a457d-dde7-459a-badf-774e8e506025\\/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg\\/v1\\/fit\\/w_150,h_150,q_70,strp\\/cope_by_pachunka_d2enxz7-150.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8","thumbnail_url_200h":"https:\\/\\/images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com\\/f\\/2b5a457d-dde7-459a-badf-774e8e506025\\/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg\\/v1\\/fill\\/w_133,h_200,q_70,strp\\/cope_by_pachunka_d2enxz7-200h.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8","thumbnail_width_200h":133,"thumbnail_height_200h":200}' +]; diff --git a/tests/cache/backend.deviantart.com.oembed.f5c96e2a92fca0dcba81bd7ce330d938.php b/tests/cache/backend.deviantart.com.oembed.f5c96e2a92fca0dcba81bd7ce330d938.php new file mode 100644 index 00000000..200d104f --- /dev/null +++ b/tests/cache/backend.deviantart.com.oembed.f5c96e2a92fca0dcba81bd7ce330d938.php @@ -0,0 +1,43 @@ + [ + 'content-type' => [ + 'text/html; charset=ISO-8859-1' + ], + 'content-length' => [ + '180' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:25:01 GMT' + ], + 'server' => [ + 'Apache' + ], + 'x-backend' => [ + 'web_http_back' + ], + 'x-cache' => [ + 'Error from cloudfront' + ], + 'via' => [ + '1.1 b6a3e4c49d0265073859268bbecf413b.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'WAW50-C1' + ], + 'x-amz-cf-id' => [ + '3fLPIshLyvdpYW2_5jPV4izBXNbb8rfpy9raBtny4h9E3SGfEeXz_A==' + ], + 'Content-Location' => [ + 'https://backend.deviantart.com/oembed?url=https%253A%252F%252Fwww.deviantart.com%252Fpachunka%252Fart%252FCope-145564099&format=json' + ], + 'X-Request-Time' => [ + '0.799 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => '404 Not Found (https%3A%2F%2Fwww.deviantart.com%2Fpachunka%2Fart%2FCope-145564099) The URL https%3A%2F%2Fwww.deviantart.com%2Fpachunka%2Fart%2FCope-145564099 is not a deviation URL' +]; diff --git a/tests/cache/buff.ly.2usohds.php b/tests/cache/buff.ly.2usohds.php new file mode 100644 index 00000000..afe267ea --- /dev/null +++ b/tests/cache/buff.ly.2usohds.php @@ -0,0 +1,1954 @@ + [ + 'cache-control' => [ + 'private, max-age=90' + ], + 'content-security-policy' => [ + 'referrer always;' + ], + 'content-type' => [ + 'text/html; charset=utf-8', + 'text/html; charset=UTF-8' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:00 GMT', + 'Sun, 04 Apr 2021 15:22:00 GMT' + ], + 'location' => [ + 'https://graffica.info/sabes-cual-es-el-origen-del-ampersand/' + ], + 'referrer-policy' => [ + 'unsafe-url' + ], + 'server' => [ + 'nginx', + 'Apache' + ], + 'set-cookie' => [ + '_bit=l34fm0-90396a14f58f8cd819-00R; Domain=buff.ly; Expires=Fri, 01 Oct 2021 15:22:00 GMT', + 'wp_woocommerce_session_a83defda688b76c558bd32cf4bb41209=943fa220fec339cb2dc4fe7d25c2311b%7C%7C1617722521%7C%7C1617718921%7C%7C578a1e7d533be4cee33a170035949791; expires=Tue, 06-Apr-2021 15:22:01 GMT; Max-Age=172800; path=/; secure; HttpOnly' + ], + 'content-length' => [ + '147 HTTP/2 200' + ], + 'x-powered-by' => [ + 'PHP/7.4.16' + ], + 'link' => [ + '; rel="https://api.w.org/", ; rel="alternate"; type="application/json", ; rel=shortlink' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'last-modified' => [ + 'Sun, 04 Apr 2021 15:22:03 GMT' + ], + 'Content-Location' => [ + 'https://graffica.info/sabes-cual-es-el-origen-del-ampersand/' + ], + 'X-Request-Time' => [ + '3.801 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + El origen del ampersand que desconocen muchos diseñadores + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + +
+
+
+ + +
+
+
+
+ +
+ +
+ + +
+
+
+
+
+ + + + +
+
+
+ + + + +
+ +
+
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+ + + + + +
+
+
+ + +
+
+ + +

No hay productos en el carrito.

+ + +
+
+ +
+
+ +
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + + +
+
+
+ + +
+
+ + +

No hay productos en el carrito.

+ + +
+
+ +
+
+ +
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ + +
+
+
+
+ + +
+
+
+ +
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+
+ + + +
+ +
+ + +
+
+ +
+ +
+
+ +
+
+
+ + +
+ +

¿Sabes cuál es el origen del ampersand?

+ + +
+
+
+ + +
+
+
+
540
+ REDES +
+
+
13.5k
+ LECTURAS +
+
+
+ + +
+
+
+
+ + + + + +
+ + +
+
+

+ Artículos

+ +
+ +
+
+ + +
+ + +
+ Siguiente + + + + +
+
+

+ Comentarios 1 +

+ +
+
    +
  1. +
    +
    + \'\' Lucio cañupan says:
    + + + +
    +

    Interesante el artículo de la Sra. Papalardo. Puedo agregar que el signo en cuestión, segun consta en estudiosos calificados, fue inventado por Marco Tulio Tiro, secretario de Cicerón, quien dictaba muy rapido, y aquél no daba abasto para las anotaciones. Fueron los inicios de la taquigrafia.

    +
    + + +
    +
  2. +
+
+ +
+ +
+

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

+ +

+ +

+ +

+
+

Información básica sobre protección de datos Ver más

+
    +
  • Responsable El titular del sitio. +
  • +
  • Finalidad  + + Moderar los comentarios. + Responder las consultas. +
  • +
  • Legitimación Tu consentimiento.
  • +
  • Destinatarios  + + . + +
  • +
  • Derechos Acceder, rectificar y suprimir los datos.
  • +
  • Información Adicional Puedes consultar la información detallada en la Política de Privacidad.
  • +
+
+

+ +

+
+
+
+ +
+
+
+ +
+ +
+ +
+ + +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ + +
+
+ +
+ +
+
+ +
+
+
+
+ +
+ + +
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ +
+ + + +
+ +
+
+
+
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+
+
+
+
+ + + + + + +
+
+
+ Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. + + + Ver Política de cookies + + +
+ +
+
+
+
+ +
+ Privacidad +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +' +]; diff --git a/tests/cache/calendar.google.com.calendar-embed.95ba7bc228ac2f81591bfa9cd9d2da50.php b/tests/cache/calendar.google.com.calendar-embed.95ba7bc228ac2f81591bfa9cd9d2da50.php new file mode 100644 index 00000000..db5905c9 --- /dev/null +++ b/tests/cache/calendar.google.com.calendar-embed.95ba7bc228ac2f81591bfa9cd9d2da50.php @@ -0,0 +1,95 @@ + [ + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:37 GMT' + ], + 'content-encoding' => [ + 'gzip' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'content-security-policy-report-only' => [ + 'script-src \'nonce-Uu+BOvH4FFqsZaWmP7DCaA\' \'unsafe-inline\' \'strict-dynamic\' https: http: \'unsafe-eval\';object-src \'none\';base-uri \'self\';report-uri /calendar/cspreport' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'server' => [ + 'GSE' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://calendar.google.com/calendar/embed?src=spain__es%40holiday.calendar.google.com&ctz=Europe/Madrid' + ], + 'X-Request-Time' => [ + '0.303 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + +Festivos en España + + + + + + + + + + + + + + +Festivos en España + + +
' +]; diff --git a/tests/cache/cdn2.thecatapi.com.images-cjd.jpg.php b/tests/cache/cdn2.thecatapi.com.images-cjd.jpg.php new file mode 100644 index 00000000..b7aa6875 --- /dev/null +++ b/tests/cache/cdn2.thecatapi.com.images-cjd.jpg.php @@ -0,0 +1,70 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:04 GMT' + ], + 'content-type' => [ + 'image/jpeg' + ], + 'content-length' => [ + '115080' + ], + 'last-modified' => [ + 'Thu, 27 Sep 2018 01:08:20 GMT' + ], + 'etag' => [ + '"cf16a912a37899c395d13e4365cddc66"' + ], + 'x-cache' => [ + 'Hit from cloudfront' + ], + 'via' => [ + '1.1 a971b2b62b734c0aed2e82b19df64026.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD56-P3' + ], + 'x-amz-cf-id' => [ + 'fOg4lsIA-UWP5Y2R0_06gp56Pu7S6FrrRwht2svV3qGDh7gSEKL-eA==' + ], + 'cache-control' => [ + 'max-age=14400' + ], + 'cf-cache-status' => [ + 'MISS' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=3WDfKJMEJ0rBrXW%2FXOU2sKArj29VhU%2F5qiUgGLs6sQD2%2BWgJQG%2BdTPFjlrW%2BCE1lqr8kcFinvr7Y52udCOmgcdgnf9xSspYimnP4jUhtzFP%2BCPVlFG%2F%2F1OPEKyqg32%2BjhHyQ8%2BA%3D"}],"group":"cf-nel","max_age":604800}' + ], + 'nel' => [ + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare' + ], + 'cf-ray' => [ + '891a9106dc28668f-MAD' + ], + 'alt-svc' => [ + 'h3=":443"; ma=86400' + ], + 'Content-Location' => [ + 'https://cdn2.thecatapi.com/images/cjd.jpg' + ], + 'X-Request-Time' => [ + '0.148 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '' +]; diff --git a/tests/cache/chirb.it.7a9l9b.php b/tests/cache/chirb.it.7a9l9b.php new file mode 100644 index 00000000..76e3a688 --- /dev/null +++ b/tests/cache/chirb.it.7a9l9b.php @@ -0,0 +1,503 @@ + [ + 'server' => [ + 'nginx/1.18.0', + 'nginx/1.18.0' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:23:44 GMT', + 'Sun, 04 Apr 2021 15:23:44 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=UTF-8' + ], + 'content-length' => [ + '169' + ], + 'connection' => [ + 'keep-alive', + 'keep-alive' + ], + 'location' => [ + 'https://chirb.it/7A9L9B%20%20HTTP/1.1%20200%20OK' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://chirb.it/7A9L9B' + ], + 'X-Request-Time' => [ + '1.018 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chirbit - Encana conference call - - share audio easily + + + Chirbit - Listen | Encana conference call + + + + +
+
+ +
+ +
+ + +
Encana conference call
+ +
+ +
+ +
+
00:00
+
00:00:19
+
+
+ +   + + +
+
+ + +
+ + #conference + +
+ + + + +
+ + + + +
+ + +
+
+ + + + + +
+
+

Comments

+ + +
+
+
+
+ + + + +
+ + + +
+

Share This Chirbit

+
+
+
+
+
+ +
+
+
+
+
+
+
+ + + +
+
+
+
+
+ +
+ +
+
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/chirb.it.oembed.json.0b6fc4888b3b29e8dea759841f8f9940.php b/tests/cache/chirb.it.oembed.json.0b6fc4888b3b29e8dea759841f8f9940.php new file mode 100644 index 00000000..2e3f9ea1 --- /dev/null +++ b/tests/cache/chirb.it.oembed.json.0b6fc4888b3b29e8dea759841f8f9940.php @@ -0,0 +1,31 @@ + [ + 'server' => [ + 'nginx/1.18.0' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:23:45 GMT' + ], + 'content-type' => [ + 'application/json' + ], + 'content-length' => [ + '627' + ], + 'connection' => [ + 'keep-alive' + ], + 'Content-Location' => [ + 'https://chirb.it/oembed.json?url=https%3A%2F%2Fchirb.it%2F7A9L9B' + ], + 'X-Request-Time' => [ + '0.629 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"rich","provider_name":"chirbit","provider_url":"https:\\/\\/www.chirbit.com\\/","thumbnail_url":"https:\\/\\/chirb.it\\/chirbit_oembedpic.jpg","thumbnail_width":120,"thumbnail_height":120,"width":"380","height":"120","title":"Encana conference call","author_name":"nvanderklippe","author_url":"https:\\/\\/www.chirbit.com\\/nvanderklippe","html":"" +} +' +]; diff --git a/tests/cache/codepen.io.zhouzi-pen-jorazp.php b/tests/cache/codepen.io.zhouzi-pen-jorazp.php new file mode 100644 index 00000000..0d5f052f --- /dev/null +++ b/tests/cache/codepen.io.zhouzi-pen-jorazp.php @@ -0,0 +1,102 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:41 GMT', + 'Mon, 10 Jun 2024 15:58:42 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=UTF-8' + ], + 'content-length' => [ + '167' + ], + 'connection' => [ + 'keep-alive' + ], + 'cache-control' => [ + 'max-age=3600', + 'private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:58:41 GMT', + 'Thu, 01 Jan 1970 00:00:01 GMT' + ], + 'location' => [ + 'https://codepen.io/Zhouzi/pen/JoRazP' + ], + 'set-cookie' => [ + '__cf_bm=gI_Gwk_P8ZL5vo.jY8BZ1WhwGZUcv08tNXlFTF9EAl4-1718035121-1.0.1.1-GRegqZMC.WUnU8T4Yvn2AiMBel5P7o5jz4IAZCz1z2Et8ItxOlDSI2FRecsvThtPpNj8nF4bwtjUSJDGEr2gTg; path=/; expires=Mon, 10-Jun-24 16:28:41 GMT; domain=.codepen.io; HttpOnly' + ], + 'vary' => [ + 'Accept-Encoding', + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a90782c62f164-CDG', + '891a9078a9911ba1-MAD' + ], + 'alt-svc' => [ + 'h3=":443"; ma=86400 HTTP/2 403', + 'h3=":443"; ma=86400' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'critical-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'cross-origin-embedder-policy' => [ + 'require-corp' + ], + 'cross-origin-opener-policy' => [ + 'same-origin' + ], + 'cross-origin-resource-policy' => [ + 'same-origin' + ], + 'origin-agent-cluster' => [ + '?1' + ], + 'permissions-policy' => [ + 'accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()' + ], + 'referrer-policy' => [ + 'same-origin' + ], + 'x-content-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'cf-mitigated' => [ + 'challenge' + ], + 'cf-chl-out' => [ + 'TXwt+Z+yS1DmlEXQy1uTi0kqcbA+lfEbKomLqau05k9G/Z3LQCWKIS3h6ffEnXYuCbvH57GnIqk5hxE1GuBuQTvv+dbml8XOFI2Y9mAp0zmn9ertXyNjbK58LEcd3tgXaQNaTbRY1eCv8YyVZHfWrQ==$SER7j/ua0QBQjIw9pUbl0w==' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://codepen.io/Zhouzi/pen/JoRazP' + ], + 'X-Request-Time' => [ + '0.176 ms' + ] + ], + 'statusCode' => 403, + 'reasonPhrase' => 'Forbidden', + 'body' => 'Just a moment...
' +]; diff --git a/tests/cache/commondatastorage.googleapis.com.gtv-videos-bucket-sample-bigbuckbunny.mp4.php b/tests/cache/commondatastorage.googleapis.com.gtv-videos-bucket-sample-bigbuckbunny.mp4.php new file mode 100644 index 00000000..d0e81682 --- /dev/null +++ b/tests/cache/commondatastorage.googleapis.com.gtv-videos-bucket-sample-bigbuckbunny.mp4.php @@ -0,0 +1,71 @@ + [ + 'expires' => [ + 'Mon, 10 Jun 2024 16:59:05 GMT' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:05 GMT' + ], + 'cache-control' => [ + 'public, max-age=3600' + ], + 'last-modified' => [ + 'Thu, 05 Dec 2013 18:43:53 GMT' + ], + 'etag' => [ + '"cab08b36195edb1a1231d2d09fa450e0"' + ], + 'x-goog-generation' => [ + '1386269033518000' + ], + 'x-goog-metageneration' => [ + '2' + ], + 'x-goog-stored-content-encoding' => [ + 'identity' + ], + 'x-goog-stored-content-length' => [ + '158008374' + ], + 'content-type' => [ + 'video/mp4' + ], + 'x-goog-hash' => [ + 'crc32c=x4GOmQ==', + 'md5=yrCLNhle2xoSMdLQn6RQ4A==' + ], + 'x-goog-storage-class' => [ + 'STANDARD' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'content-length' => [ + '158008374' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'access-control-expose-headers' => [ + 'origin, range' + ], + 'x-guploader-uploadid' => [ + 'ABPtcPrwRwH63sHusAt2lKA5_rkuNah4cbGd8UkcGSUDepJ6nlqFv6U15NcIRP9og-uJWSP3xxA5fO1WRg' + ], + 'server' => [ + 'UploadServer' + ], + 'Content-Location' => [ + 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4' + ], + 'X-Request-Time' => [ + '0.262 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '' +]; diff --git a/tests/cache/consent.google.es.https-consent.google.es-ml.20a3573a47b367de5e1ec943cfa5600f.php b/tests/cache/consent.google.es.https-consent.google.es-ml.20a3573a47b367de5e1ec943cfa5600f.php new file mode 100644 index 00000000..237e70c7 --- /dev/null +++ b/tests/cache/consent.google.es.https-consent.google.es-ml.20a3573a47b367de5e1ec943cfa5600f.php @@ -0,0 +1,56 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:20:47 GMT' + ], + 'p3p' => [ + 'CP="This is not a P3P policy! See g.co/p3phelp for more info."' + ], + 'content-security-policy' => [ + 'script-src \'nonce-g9/eaYJePAYsVh50Jyl0EQ\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/IdentityNotFoundHttp/cspreport;worker-src \'self\'', + 'script-src \'nonce-g9/eaYJePAYsVh50Jyl0EQ\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/IdentityNotFoundHttp/cspreport' + ], + 'content-encoding' => [ + 'gzip' + ], + 'server' => [ + 'ESF' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'set-cookie' => [ + 'NID=212=dAlC8GKROGQ6cWC5EeQ92vga0m4ReROz1kMl9BrboOg7GfaE3zvV7pmmgCmsXsJ7vya8tJGI4jioBfUTai-FbFjJPm264-_PY9-GEu66UJhCsRvBiDJVz3O5Ckjox4e0LsT9RZ2vuLADiJTrbw7nzwn4qwyWUF3duIq6_ZUnLhA; expires=Mon, 04-Oct-2021 15:20:47 GMT; path=/; domain=.google.es; Secure; HttpOnly; SameSite=none' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://consent.google.es//'https:/consent.google.es/ml?continue=https://www.google.es/maps/place/Tordoia,%2BA%2BCoru%25C3%25B1a/@43.0871207,-8.5710004,12z/data%3D!3m1!4b1!4m2!3m1!1s0xd2ef4006f1ef489:0x404f58273ca55a0&gl=ES&hl=es&pc=m&src=1&rffu=true\'' + ], + 'X-Request-Time' => [ + '0.112 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => 'Error 404 (No se ha encontrado.)!!1

404. Se trata de un error.

No se ha encontrado la URL solicitada en este servidor. Esa es toda la información de la que disponemos.

' +]; diff --git a/tests/cache/consent.google.es.ml.0bcc06470676961770c2d2357693454b.php b/tests/cache/consent.google.es.ml.0bcc06470676961770c2d2357693454b.php new file mode 100644 index 00000000..237e70c7 --- /dev/null +++ b/tests/cache/consent.google.es.ml.0bcc06470676961770c2d2357693454b.php @@ -0,0 +1,56 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:20:47 GMT' + ], + 'p3p' => [ + 'CP="This is not a P3P policy! See g.co/p3phelp for more info."' + ], + 'content-security-policy' => [ + 'script-src \'nonce-g9/eaYJePAYsVh50Jyl0EQ\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/IdentityNotFoundHttp/cspreport;worker-src \'self\'', + 'script-src \'nonce-g9/eaYJePAYsVh50Jyl0EQ\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/IdentityNotFoundHttp/cspreport' + ], + 'content-encoding' => [ + 'gzip' + ], + 'server' => [ + 'ESF' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'set-cookie' => [ + 'NID=212=dAlC8GKROGQ6cWC5EeQ92vga0m4ReROz1kMl9BrboOg7GfaE3zvV7pmmgCmsXsJ7vya8tJGI4jioBfUTai-FbFjJPm264-_PY9-GEu66UJhCsRvBiDJVz3O5Ckjox4e0LsT9RZ2vuLADiJTrbw7nzwn4qwyWUF3duIq6_ZUnLhA; expires=Mon, 04-Oct-2021 15:20:47 GMT; path=/; domain=.google.es; Secure; HttpOnly; SameSite=none' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://consent.google.es//'https:/consent.google.es/ml?continue=https://www.google.es/maps/place/Tordoia,%2BA%2BCoru%25C3%25B1a/@43.0871207,-8.5710004,12z/data%3D!3m1!4b1!4m2!3m1!1s0xd2ef4006f1ef489:0x404f58273ca55a0&gl=ES&hl=es&pc=m&src=1&rffu=true\'' + ], + 'X-Request-Time' => [ + '0.112 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => 'Error 404 (No se ha encontrado.)!!1

404. Se trata de un error.

No se ha encontrado la URL solicitada en este servidor. Esa es toda la información de la que disponemos.

' +]; diff --git a/tests/cache/consent.google.es.ml.2d8b4c7aacb24b7a0a3dabeac8b062b4.php b/tests/cache/consent.google.es.ml.2d8b4c7aacb24b7a0a3dabeac8b062b4.php new file mode 100644 index 00000000..63a453ac --- /dev/null +++ b/tests/cache/consent.google.es.ml.2d8b4c7aacb24b7a0a3dabeac8b062b4.php @@ -0,0 +1,729 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'vary' => [ + 'Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:25 GMT' + ], + 'content-security-policy' => [ + 'require-trusted-types-for \'script\';report-uri /_/ConsentHttp/cspreport', + 'script-src \'nonce-n6pzNMlHdulPSPvgDwWTAQ\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/ConsentHttp/cspreport;worker-src \'self\'', + 'script-src \'unsafe-inline\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.googletagmanager.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/ConsentHttp/cspreport/allowlist' + ], + 'permissions-policy' => [ + 'ch-ua-arch=*, ch-ua-bitness=*, ch-ua-full-version=*, ch-ua-full-version-list=*, ch-ua-model=*, ch-ua-wow64=*, ch-ua-form-factor=*, ch-ua-platform=*, ch-ua-platform-version=*' + ], + 'cross-origin-opener-policy' => [ + 'unsafe-none' + ], + 'cross-origin-resource-policy' => [ + 'same-site' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Full-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Model, Sec-CH-UA-WoW64, Sec-CH-UA-Form-Factor, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version' + ], + 'reporting-endpoints' => [ + 'default="/_/ConsentHttp/web-reports?context=eJzj8tHikmJw0JBisLi3g-l8xi6m19a3mCS-vmTSAGKn9BmsQUDsUz-DNQaIW2-eY50KxEn_zrMWAXH75wus04F4ScRF1kOJF1mFuDnuHp2zmU2gYdoVdSXtpPzC-MyU1LySzJLKtKL8vJLUvJTSzOLUorLUongjAyMTAzMDEz0Dk_gCAwDWfza3"' + ], + 'content-encoding' => [ + 'gzip' + ], + 'server' => [ + 'ESF' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'set-cookie' => [ + '__Secure-BUCKET=CLUD; Domain=.google.es; Expires=Sat, 07-Dec-2024 15:59:25 GMT; Path=/; Secure; HttpOnly; SameSite=lax' + ], + 'alt-svc' => [ + 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000' + ], + 'Content-Location' => [ + 'https://consent.google.es/ml?continue=https://www.google.es/maps/place/Tordoia,%2BA%2BCoru%25C3%25B1a/@43.0871207,-8.5710004,12z/data%3D!3m1!4b1!4m2!3m1!1s0xd2ef4006f1ef489:0x404f58273ca55a0&gl=ES&hl=es&cm=2&pc=m&uxe=eomtm&src=1&rffu=true' + ], + 'X-Request-Time' => [ + '0.122 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Antes de ir a Google Maps

Antes de ir a Google

Usamos cookies y datos para:

  • Proporcionar y mantener nuestros servicios
  • Hacer un seguimiento de las interrupciones y prevenir el spam, el fraude y los abusos
  • Medir la interacción de la audiencia y estadísticas de los sitios para entender cómo se utilizan nuestros servicios y mejorar su calidad

Si eliges Aceptar todo, también usaremos cookies y datos para:

  • Desarrollar y mejorar nuevos servicios
  • Proporcionar anuncios y medir su eficacia
  • Mostrar contenido personalizado en función de tus ajustes
  • Mostrar anuncios personalizados en función de tus ajustes

Si eliges Rechazar todo, no usaremos cookies para estos fines adicionales.

El contenido no personalizado está influido por factores como lo que estés viendo en ese momento, la actividad de tu sesión de búsqueda activa y tu ubicación. Los anuncios no personalizados están influidos por lo que estés viendo en ese momento y tu ubicación general. El contenido y los anuncios personalizados también pueden incluir resultados y recomendaciones más relevantes, así como anuncios basados en la actividad que se haya realizado previamente con este navegador, como búsquedas en Google anteriores. En caso necesario, también usamos cookies y datos para adaptar la experiencia de modo que sea apropiada para determinada edad.

Selecciona Más opciones para ver información adicional, como detalles sobre la gestión de la configuración de privacidad. También puedes visitar g.co/privacytools/es en cualquier momento.

' +]; diff --git a/tests/cache/consent.youtube.com.https-consent.youtube.com-ml.1e8880920f82edebd2e133df8917d407.php b/tests/cache/consent.youtube.com.https-consent.youtube.com-ml.1e8880920f82edebd2e133df8917d407.php new file mode 100644 index 00000000..20837910 --- /dev/null +++ b/tests/cache/consent.youtube.com.https-consent.youtube.com-ml.1e8880920f82edebd2e133df8917d407.php @@ -0,0 +1,50 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:23:17 GMT' + ], + 'content-security-policy' => [ + 'script-src \'nonce-vsx63Xooae1XpA8j6kEGNA\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/IdentityNotFoundHttp/cspreport;worker-src \'self\'', + 'script-src \'nonce-vsx63Xooae1XpA8j6kEGNA\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/IdentityNotFoundHttp/cspreport' + ], + 'content-encoding' => [ + 'gzip' + ], + 'server' => [ + 'ESF' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://consent.youtube.com//'https:/consent.youtube.com/ml?continue=https://www.youtube.com/channel/UCuZeHD5SGecQomz2pVDHGzg&gl=ES&hl=es&pc=yt&uxe=23983172&src=1&rffu=true\'' + ], + 'X-Request-Time' => [ + '0.127 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => 'Error 404 (No se ha encontrado.)!!1

404. Se trata de un error.

No se ha encontrado la URL solicitada en este servidor. Esa es toda la información de la que disponemos.

' +]; diff --git a/tests/cache/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.ph b/tests/cache/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.ph new file mode 100644 index 00000000..20837910 --- /dev/null +++ b/tests/cache/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.ph @@ -0,0 +1,50 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:23:17 GMT' + ], + 'content-security-policy' => [ + 'script-src \'nonce-vsx63Xooae1XpA8j6kEGNA\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/IdentityNotFoundHttp/cspreport;worker-src \'self\'', + 'script-src \'nonce-vsx63Xooae1XpA8j6kEGNA\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/IdentityNotFoundHttp/cspreport' + ], + 'content-encoding' => [ + 'gzip' + ], + 'server' => [ + 'ESF' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://consent.youtube.com//'https:/consent.youtube.com/ml?continue=https://www.youtube.com/channel/UCuZeHD5SGecQomz2pVDHGzg&gl=ES&hl=es&pc=yt&uxe=23983172&src=1&rffu=true\'' + ], + 'X-Request-Time' => [ + '0.127 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => 'Error 404 (No se ha encontrado.)!!1

404. Se trata de un error.

No se ha encontrado la URL solicitada en este servidor. Esa es toda la información de la que disponemos.

' +]; diff --git a/tests/cache/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.php b/tests/cache/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.php new file mode 100644 index 00000000..20837910 --- /dev/null +++ b/tests/cache/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.php @@ -0,0 +1,50 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:23:17 GMT' + ], + 'content-security-policy' => [ + 'script-src \'nonce-vsx63Xooae1XpA8j6kEGNA\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/IdentityNotFoundHttp/cspreport;worker-src \'self\'', + 'script-src \'nonce-vsx63Xooae1XpA8j6kEGNA\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/IdentityNotFoundHttp/cspreport' + ], + 'content-encoding' => [ + 'gzip' + ], + 'server' => [ + 'ESF' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://consent.youtube.com//'https:/consent.youtube.com/ml?continue=https://www.youtube.com/channel/UCuZeHD5SGecQomz2pVDHGzg&gl=ES&hl=es&pc=yt&uxe=23983172&src=1&rffu=true\'' + ], + 'X-Request-Time' => [ + '0.127 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => 'Error 404 (No se ha encontrado.)!!1

404. Se trata de un error.

No se ha encontrado la URL solicitada en este servidor. Esa es toda la información de la que disponemos.

' +]; diff --git a/tests/cache/css-tricks.com.css-scrollbar-with-progress-meter.php b/tests/cache/css-tricks.com.css-scrollbar-with-progress-meter.php new file mode 100644 index 00000000..9bd8aa80 --- /dev/null +++ b/tests/cache/css-tricks.com.css-scrollbar-with-progress-meter.php @@ -0,0 +1,689 @@ + [ + 'date' => [ + 'Sun, 04 Apr 2021 15:20:02 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'set-cookie' => [ + '__cfduid=d68f1a9952f831a37f1937778c7bf443f1617549602; expires=Tue, 04-May-21 15:20:02 GMT; path=/; domain=.css-tricks.com; HttpOnly; SameSite=Lax; Secure' + ], + 'cf-ray' => [ + '63ab84b4cb9d540a-LHR' + ], + 'age' => [ + '139840' + ], + 'cache-control' => [ + 'max-age=14400' + ], + 'link' => [ + '; rel="https://api.w.org/", ; rel="alternate"; type="application/json", ; rel=shortlink' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'vary' => [ + 'Accept-Encoding, Authorization' + ], + 'cf-cache-status' => [ + 'HIT' + ], + 'cf-apo-via' => [ + 'tcache' + ], + 'cf-edge-cache' => [ + 'cache,platform=wordpress' + ], + 'cf-request-id' => [ + '093f1145070000540aa1280000000001' + ], + 'expect-ct' => [ + 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"' + ], + 'fastly-restarts' => [ + '1' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'x-cache' => [ + 'MISS' + ], + 'x-cache-hits' => [ + '0' + ], + 'x-cacheable' => [ + 'YES' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-fw-dynamic' => [ + 'TRUE' + ], + 'x-fw-hash' => [ + 'lwxgywlq8s' + ], + 'x-fw-serve' => [ + 'TRUE' + ], + 'x-fw-server' => [ + 'Flywheel/5.1.0' + ], + 'x-fw-static' => [ + 'NO' + ], + 'x-fw-type' => [ + 'FLYWHEEL_BOT' + ], + 'x-fw-version' => [ + '5.0.0' + ], + 'x-served-by' => [ + 'cache-lcy19231-LCY' + ], + 'x-timer' => [ + 'S1617409761.437001,VS0,VE812' + ], + 'x-xss-protection' => [ + '1' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=UFOebRBLgC6Pa32KLZvYv9AcpURAuolRV4dzot3lQSyM%2BtZJrCyxcsEne1NdtG%2BtYao30HX%2FJKa5qjX5lctFDsm7H81N7WrtPSknTLXf0g%3D%3D"}],"max_age":604800,"group":"cf-nel"}' + ], + 'nel' => [ + '{"max_age":604800,"report_to":"cf-nel"}' + ], + 'server' => [ + 'cloudflare' + ], + 'content-encoding' => [ + 'br' + ], + 'alt-svc' => [ + 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400' + ], + 'Content-Location' => [ + 'https://css-tricks.com/css-scrollbar-with-progress-meter/' + ], + 'X-Request-Time' => [ + '0.268 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + CSS Scrollbar With Progress Meter | CSS-Tricks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+ +

+CSS Scrollbar With Progress Meter

+
+ +Avatar of Chris Coyier +
+ +Chris Coyier +on + +
+
+
+
+

+Take the pain out of building site search with the Algolia hosted API. Start free now! +

+
+
+

Scrollbars are natural progress meters. How far the scrollbar is down or across is how much progress has been made scrolling through that element (often the entire page). But, they are more like progress indicators than meters, if you think of a meter as something that “fills up” as you go.

+

We can use some CSS trickery to make the scrollbar fill up as we go.

+ +

This will only work with -webkit- vendor-prefixed scrollbar-styling properties. In other words, these are non-standard. The standardized scrollbar styling properties are scrollbar-width and scrollbar-color, which can’t pull this kind of thing off, but are probably a safer bet in the long run. Still, the vendor-prefixed versions probably aren’t going anywhere, so if you consider this a weird form of progressive enhancement, that’s probably fine.

+

What’s the trick?

+

Essentially, it’s hanging a huge box-shadow off the top of the scrollbar thumb — or off the side if it’s a horizontally scrolling element.

+
:root {
+  --shadow: #43a047;
+  --scrollbarBG: #eee;
+  --thumbBG: #66bb6a;
+}
+::-webkit-scrollbar {
+  width: 16px;
+}
+::-webkit-scrollbar-track {
+  background: var(--scrollbarBG);
+}
+::-webkit-scrollbar-thumb {
+  background-color: var(--thumbBG);
+  box-shadow: 0 -100vh 0 100vh var(--shadow), 0 0 15px 5px black;
+}
+

Demo

+
+

I first saw this in a Pen by Myk.

+

That example didn’t differentiate the thumb part of the scrollbar at all, which makes it more meter-like, but also harder to use. My demo has a slightly different color thumb.

+

Can I really use this?

+

No! Aside from it being super weird and non-standard. Safari flips it’s lid and I have no idea how to fix it.

+
+

I do happen to have a favorite CSS trick that is highly related to this though.

+

I want to learn more about styling scrollbars

+

Cool, here you go.

+
+
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/css-tricks.com.wp-json-oembed-1.0-embed.6fa621075f5777043924a477822901f6.php b/tests/cache/css-tricks.com.wp-json-oembed-1.0-embed.6fa621075f5777043924a477822901f6.php new file mode 100644 index 00000000..175aa3f6 --- /dev/null +++ b/tests/cache/css-tricks.com.wp-json-oembed-1.0-embed.6fa621075f5777043924a477822901f6.php @@ -0,0 +1,127 @@ + [ + 'date' => [ + 'Sun, 04 Apr 2021 15:20:02 GMT' + ], + 'content-type' => [ + 'application/json; charset=UTF-8' + ], + 'set-cookie' => [ + '__cfduid=dab9d4d918c5dea242d69a2a45f89476c1617549602; expires=Tue, 04-May-21 15:20:02 GMT; path=/; domain=.css-tricks.com; HttpOnly; SameSite=Lax; Secure' + ], + 'cf-ray' => [ + '63ab84b688ac0026-LHR' + ], + 'allow' => [ + 'GET' + ], + 'link' => [ + '; rel="https://api.w.org/"' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'vary' => [ + 'Accept-Encoding, Origin, Authorization' + ], + 'cf-cache-status' => [ + 'BYPASS' + ], + 'access-control-allow-headers' => [ + 'Authorization, X-WP-Nonce, Content-Disposition, Content-MD5, Content-Type' + ], + 'access-control-expose-headers' => [ + 'X-WP-Total, X-WP-TotalPages, Link' + ], + 'cf-apo-via' => [ + 'origin,qs' + ], + 'cf-edge-cache' => [ + 'cache,platform=wordpress' + ], + 'cf-request-id' => [ + '093f11461b00000026cd826000000001' + ], + 'expect-ct' => [ + 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"' + ], + 'fastly-restarts' => [ + '1' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'x-cache' => [ + 'MISS' + ], + 'x-cache-hits' => [ + '0' + ], + 'x-cacheable' => [ + 'YES' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-fw-dynamic' => [ + 'TRUE' + ], + 'x-fw-hash' => [ + 'lwxgywlq8s' + ], + 'x-fw-serve' => [ + 'TRUE' + ], + 'x-fw-server' => [ + 'Flywheel/5.1.0' + ], + 'x-fw-static' => [ + 'YES' + ], + 'x-fw-type' => [ + 'VISIT' + ], + 'x-fw-version' => [ + '5.0.0' + ], + 'x-robots-tag' => [ + 'noindex' + ], + 'x-served-by' => [ + 'cache-lcy19260-LCY' + ], + 'x-timer' => [ + 'S1617549602.363610,VS0,VE493' + ], + 'x-xss-protection' => [ + '1' + ], + 'report-to' => [ + '{"group":"cf-nel","endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=HwxScNeMtOe4xcnoQG1wR9DNPJsS1iT%2BzuuWwSmK8BjImMTBUHYnvjfS2fHuXhcE41%2FpAN1cRb0kPuq9ElltddQxg8j7vCksKWfVtsRWKQ%3D%3D"}],"max_age":604800}' + ], + 'nel' => [ + '{"report_to":"cf-nel","max_age":604800}' + ], + 'server' => [ + 'cloudflare' + ], + 'content-encoding' => [ + 'br' + ], + 'alt-svc' => [ + 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400' + ], + 'Content-Location' => [ + 'https://css-tricks.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fcss-tricks.com%2Fcss-scrollbar-with-progress-meter%2F' + ], + 'X-Request-Time' => [ + '2.121 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","provider_name":"CSS-Tricks","provider_url":"https:\\/\\/css-tricks.com","author_name":"Chris Coyier","author_url":"https:\\/\\/css-tricks.com\\/author\\/chriscoyier\\/","title":"CSS Scrollbar With Progress Meter | CSS-Tricks","type":"rich","width":600,"height":338,"html":"
CSS Scrollbar With Progress Meter<\\/a><\\/blockquote>\\n
Logotipo de Google
No se puede acceder a tu cuenta de Google
Ahora mismo no podemos acceder a este contenido. Prueba a iniciar sesión en tu cuenta de Google o a permitir el acceso a las cookies para continuar.
' +]; diff --git a/tests/cache/embed.spotify.com.oembed.ef6aab8b5691cc9b9da2dc988f19e9e2.php b/tests/cache/embed.spotify.com.oembed.ef6aab8b5691cc9b9da2dc988f19e9e2.php new file mode 100644 index 00000000..f697f3aa --- /dev/null +++ b/tests/cache/embed.spotify.com.oembed.ef6aab8b5691cc9b9da2dc988f19e9e2.php @@ -0,0 +1,72 @@ + [ + 'server' => [ + 'envoy', + 'envoy', + 'envoy' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:20:48 GMT', + 'Sun, 04 Apr 2021 15:20:48 GMT', + 'Sun, 04 Apr 2021 15:20:48 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html', + 'application/json; charset=utf-8' + ], + 'location' => [ + 'https://open.spotify.com/oembed/?url=https%3A%2F%2Fopen.spotify.com%2Falbum%2F7s66wU1XJ2NsUuWM2NKiUV&format=json', + 'https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Falbum%2F7s66wU1XJ2NsUuWM2NKiUV&format=json' + ], + 'strict-transport-security' => [ + 'max-age=31536000', + 'max-age=31536000', + 'max-age=31536000' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff', + 'nosniff' + ], + 'content-encoding' => [ + 'gzip', + 'gzip', + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding', + 'Accept-Encoding', + 'Accept-Encoding,Accept-Encoding' + ], + 'via' => [ + 'HTTP/2 edgeproxy, 1.1 google', + 'HTTP/2 edgeproxy, 1.1 google', + 'HTTP/2 edgeproxy, 1.1 google' + ], + 'alt-svc' => [ + 'clear HTTP/2 301', + 'clear HTTP/2 200', + 'clear' + ], + 'spotify-request-id' => [ + 'd23d3b20-0868-423e-9d1e-fc3c1bcf9703' + ], + 'set-cookie' => [ + 'sp_t=f1fda6f431b00e9d674a0f5e4a2a58d2; path=/; expires=Mon, 04 Apr 2022 15:20:48 GMT; domain=.spotify.com; samesite=none; secure', + 'sp_landing=https%3A%2F%2Fopen.spotify.com%2Foembed; path=/; expires=Mon, 05 Apr 2021 15:20:48 GMT; domain=.spotify.com; samesite=none; secure; httponly' + ], + 'Content-Location' => [ + 'https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Falbum%2F7s66wU1XJ2NsUuWM2NKiUV&format=json' + ], + 'X-Request-Time' => [ + '0.240 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"html":"","width":300,"height":380,"version":"1.0","provider_name":"Spotify","provider_url":"https://spotify.com/","type":"rich","title":"A Cantar con Xabarin (Vol. I & II)","thumbnail_url":"https://i.scdn.co/image/ab67616d00001e02022aca057f08a1d40c1f0733","thumbnail_width":300,"thumbnail_height":300}' +]; diff --git a/tests/cache/en.wikipedia.org.w-api.php.502f13ee76100c314d882dd6cbc87af2.php b/tests/cache/en.wikipedia.org.w-api.php.502f13ee76100c314d882dd6cbc87af2.php new file mode 100644 index 00000000..df7cf052 --- /dev/null +++ b/tests/cache/en.wikipedia.org.w-api.php.502f13ee76100c314d882dd6cbc87af2.php @@ -0,0 +1,73 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:20 GMT' + ], + 'server' => [ + 'mw-api-ext.eqiad.main-58fb894d6b-9gjtq' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'DENY' + ], + 'content-disposition' => [ + 'inline; filename=api-result.json' + ], + 'vary' => [ + 'Accept-Encoding,Treat-as-Untrusted,X-Forwarded-Proto,Cookie,Authorization' + ], + 'cache-control' => [ + 'private, must-revalidate, max-age=0' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'content-encoding' => [ + 'gzip' + ], + 'age' => [ + '0' + ], + 'x-cache' => [ + 'cp6012 miss, cp6016 pass' + ], + 'x-cache-status' => [ + 'pass' + ], + 'server-timing' => [ + 'cache;desc="pass", host;desc="cp6016"' + ], + 'strict-transport-security' => [ + 'max-age=106384710; includeSubDomains; preload' + ], + 'report-to' => [ + '{ "group": "wm_nel", "max_age": 604800, "endpoints": [{ "url": "https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0" }] }' + ], + 'nel' => [ + '{ "report_to": "wm_nel", "max_age": 604800, "failure_fraction": 0.05, "success_fraction": 0.0}' + ], + 'x-client-ip' => [ + '89.141.175.178' + ], + 'set-cookie' => [ + 'NetworkProbeLimit=0.001;Path=/;Secure;SameSite=Lax;Max-Age=3600' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'Content-Location' => [ + 'https://en.wikipedia.org/w/api.php?action=query&format=json&continue=&titles=Albert_Einstein&prop=extracts&exchars=1000' + ], + 'X-Request-Time' => [ + '0.282 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"batchcomplete":"","warnings":{"extracts":{"*":"HTML may be malformed and/or unbalanced and may omit inline images. Use at your own risk. Known problems are listed at https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:TextExtracts#Caveats."}},"query":{"normalized":[{"from":"Albert_Einstein","to":"Albert Einstein"}],"pages":{"736":{"pageid":736,"ns":0,"title":"Albert Einstein","extract":"

\\n\\n\\n\\n

\\n\\n

Albert Einstein ( EYEN-styne; German: [\\u02c8alb\\u025b\\u0250t \\u02c8\\u0294a\\u026an\\u0283ta\\u026an] ; 14 March 1879 \\u2013 18 April 1955) was a German-born theoretical physicist who is widely held to be one of the greatest and most influential scientists of all time. Best known for developing the theory of relativity, Einstein also made important contributions to quantum mechanics, and was thus a central figure in the revolutionary reshaping of the scientific understanding of nature that modern physics accomplished in the first decades of the twentieth century. His mass\\u2013energy equivalence formula E = mc2, which arises from relativity theory, has been called \\"the world\'s most famous equation\\". He received the 1921 Nobel Prize in Physics \\"for his services to theoretical physics, and especially for his discovery of the law

..."}}}}' +]; diff --git a/tests/cache/en.wikipedia.org.wiki-albert_einstein.php b/tests/cache/en.wikipedia.org.wiki-albert_einstein.php new file mode 100644 index 00000000..c8fbfd3d --- /dev/null +++ b/tests/cache/en.wikipedia.org.wiki-albert_einstein.php @@ -0,0 +1,3436 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 13:42:59 GMT' + ], + 'server' => [ + 'mw1373.eqiad.wmnet' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'content-language' => [ + 'en' + ], + 'origin-trial' => [ + 'AonOP4SwCrqpb0nhZbg554z9iJimP3DxUDB8V4yu9fyyepauGKD0NXqTknWi4gnuDfMG6hNb7TDUDTsl0mDw9gIAAABmeyJvcmlnaW4iOiJodHRwczovL3dpa2lwZWRpYS5vcmc6NDQzIiwiZmVhdHVyZSI6IlRvcExldmVsVHBjZCIsImV4cGlyeSI6MTczNTM0Mzk5OSwiaXNTdWJkb21haW4iOnRydWV9' + ], + 'accept-ch' => [ + '' + ], + 'vary' => [ + 'Accept-Encoding,Cookie,Authorization' + ], + 'last-modified' => [ + 'Mon, 10 Jun 2024 13:41:10 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'content-encoding' => [ + 'gzip' + ], + 'age' => [ + '8180' + ], + 'x-cache' => [ + 'cp6012 hit, cp6016 hit/21' + ], + 'x-cache-status' => [ + 'hit-front' + ], + 'server-timing' => [ + 'cache;desc="hit-front", host;desc="cp6016"' + ], + 'strict-transport-security' => [ + 'max-age=106384710; includeSubDomains; preload' + ], + 'report-to' => [ + '{ "group": "wm_nel", "max_age": 604800, "endpoints": [{ "url": "https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0" }] }' + ], + 'nel' => [ + '{ "report_to": "wm_nel", "max_age": 604800, "failure_fraction": 0.05, "success_fraction": 0.0}' + ], + 'set-cookie' => [ + 'WMF-Last-Access=10-Jun-2024;Path=/;HttpOnly;secure;Expires=Fri, 12 Jul 2024 12:00:00 GMT', + 'WMF-Last-Access-Global=10-Jun-2024;Path=/;Domain=.wikipedia.org;HttpOnly;secure;Expires=Fri, 12 Jul 2024 12:00:00 GMT', + 'WMF-DP=775;Path=/;HttpOnly;secure;Expires=Tue, 11 Jun 2024 00:00:00 GMT', + 'GeoIP=ES:GA:A_Coru__a:43.35:-8.41:v4; Path=/; secure; Domain=.wikipedia.org', + 'NetworkProbeLimit=0.001;Path=/;Secure;SameSite=Lax;Max-Age=3600' + ], + 'x-client-ip' => [ + '89.141.175.178' + ], + 'cache-control' => [ + 'private, s-maxage=0, max-age=0, must-revalidate' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'content-length' => [ + '191992' + ], + 'Content-Location' => [ + 'https://en.wikipedia.org/wiki/Albert_Einstein' + ], + 'X-Request-Time' => [ + '0.201 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + +Albert Einstein - Wikipedia + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Jump to content +
+
+
+ + + + +
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+ +

Albert Einstein

+ +
+ + +
+ +
+ + + +
+ +
+
+
+
+
+
+ +
+
+ + + +
+
+
+
+
+ + +
+
+
+
+
+
This is a good article. Click here for more information.
+
Page semi-protected
+
+ +
From Wikipedia, the free encyclopedia
+
+
+ + +
+ +

+ + + +

+
Albert Einstein
Einstein in 1921
Born(1879-03-14)14 March 1879
Ulm, Kingdom of Württemberg, German Empire
Died18 April 1955(1955-04-18) (aged 76)
Citizenship
+ +
EducationETH Zurich (Dipl., 1900)
University of Zurich (PhD, 1905)
Known for
Spouses
+
+
+
(m. 1903; div. 1919)
+
+
+
(m. 1919; died 1936)
+
Children
Awards
Scientific career
FieldsPhysics
Institutions
+ +
ThesisEine neue Bestimmung der Moleküldimensionen (A New Determination of Molecular Dimensions) (1905)
Doctoral advisorAlfred Kleiner
Other academic advisorsHeinrich Friedrich Weber
+
Signature
+
+

Albert Einstein (/ˈnstn/ EYEN-styne;[4] German: [ˈalbɛɐt ˈʔaɪnʃtaɪn] ; 14 March 1879 – 18 April 1955) was a German-born theoretical physicist who is widely held to be one of the greatest and most influential scientists of all time. Best known for developing the theory of relativity, Einstein also made important contributions to quantum mechanics, and was thus a central figure in the revolutionary reshaping of the scientific understanding of nature that modern physics accomplished in the first decades of the twentieth century.[1][5] His mass–energy equivalence formula E = mc2, which arises from relativity theory, has been called "the world\'s most famous equation".[6] He received the 1921 Nobel Prize in Physics "for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect",[7] a pivotal step in the development of quantum theory. His work is also known for its influence on the philosophy of science.[8][9] +

Born in the German Empire, Einstein moved to Switzerland in 1895, forsaking his German citizenship (as a subject of the Kingdom of Württemberg)[note 1] the following year. In 1897, at the age of seventeen, he enrolled in the mathematics and physics teaching diploma program at the Swiss federal polytechnic school in Zürich, graduating in 1900. In 1901, he acquired Swiss citizenship, which he kept for the rest of his life. In 1903, he secured a permanent position at the Swiss Patent Office in Bern. In 1905, he submitted a successful PhD dissertation to the University of Zurich. In 1914, he moved to Berlin in order to join the Prussian Academy of Sciences and the Humboldt University of Berlin. In 1917, he became director of the Kaiser Wilhelm Institute for Physics; he also became a German citizen again, this time as a subject of the Kingdom of Prussia.[note 1] +

In 1933, while he was visiting the United States, Adolf Hitler came to power in Germany. Horrified by the Nazi "war of extermination" against his fellow Jews,[10] Einstein decided to remain in the US, and was granted American citizenship in 1940.[11] On the eve of World War II, he endorsed a letter to President Franklin D. Roosevelt alerting him to the potential German nuclear weapons program and recommending that the US begin similar research. Einstein supported the Allies but generally viewed the idea of nuclear weapons with great dismay.[12] +

In 1905, sometimes described as his annus mirabilis (miracle year), Einstein published four groundbreaking papers.[13] These outlined a theory of the photoelectric effect, explained Brownian motion, introduced his special theory of relativity—a theory which addressed the inability of classical mechanics to account satisfactorily for the behavior of the electromagnetic field—and demonstrated that if the special theory is correct, mass and energy are equivalent to each other. In 1915, he proposed a general theory of relativity that extended his system of mechanics to incorporate gravitation. A cosmological paper that he published the following year laid out the implications of general relativity for the modeling of the structure and evolution of the universe as a whole.[14][15] The middle part of his career also saw him making important contributions to statistical mechanics and quantum theory. Especially notable was his work on the quantum physics of radiation, in which light consists of particles, subsequently called photons. With the Indian physicist Satyendra Nath Bose, he laid the groundwork for Bose-Einstein statistics. For much of the last phase of his academic life, Einstein worked on two endeavors that proved ultimately unsuccessful. First, he advocated against quantum theory\'s introduction of fundamental randomness into science\'s picture of the world, objecting that "God does not play dice".[16] Second, he attempted to devise a unified field theory by generalizing his geometric theory of gravitation to include electromagnetism too. As a result, he became increasingly isolated from the mainstream of modern physics. +

In a 1999 poll of 130 leading physicists worldwide by the British journal Physics World, Einstein was ranked the greatest physicist of all time.[17] His intellectual achievements and originality have made the word Einstein broadly synonymous with genius.[18] +

+ +

Life and career

+

Childhood, youth and education

+ +
A young boy with short hair and a round face, wearing a white collar and large bow, with vest, coat, skirt, and high boots. He is leaning against an ornate chair.
Einstein in 1882, age 3
+

Albert Einstein was born in Ulm,[19] in the Kingdom of Württemberg in the German Empire, on 14 March 1879.[20][21] His parents, secular Ashkenazi Jews, were Hermann Einstein, a salesman and engineer, and Pauline Koch. In 1880, the family moved to Munich\'s borough of Ludwigsvorstadt-Isarvorstadt, where Einstein\'s father and his uncle Jakob founded Elektrotechnische Fabrik J. Einstein & Cie, a company that manufactured electrical equipment based on direct current.[19] +

Albert attended St.Peter‘s Catholic elementary school in Munich from the age of five. When he was eight, he was transferred to the Luitpold Gymnasium, where he received advanced primary and then secondary school education.[22] +

In 1894, Hermann and Jakob\'s company tendered for a contract to install electric lighting in Munich, but without success—they lacked the capital that would have been required to update their technology from direct current to the more efficient, alternating current alternative.[23] The failure of their bid forced them to sell their Munich factory and search for new opportunities elsewhere. The Einstein family moved to Italy, first to Milan and a few months later to Pavia, where they settled in Palazzo Cornazzani.[24] Einstein, then fifteen, stayed behind in Munich in order to finish his schooling. His father wanted him to study electrical engineering, but he was a fractious pupil who found the Gymnasium\'s regimen and teaching methods far from congenial. He later wrote that the school\'s policy of strict rote learning was harmful to creativity. At the end of December 1894, a letter from a doctor persuaded the Luitpold\'s authorities to release him from its care, and he joined his family in Pavia.[25] While in Italy as a teenager, he wrote an essay entitled "On the Investigation of the State of the Ether in a Magnetic Field".[26][27] +

Einstein excelled at physics and mathematics from an early age, and soon acquired the mathematical expertise normally only found in a child several years his senior. He began teaching himself algebra, calculus and Euclidean geometry when he was twelve; he made such rapid progress that he discovered an original proof of the Pythagorean theorem before his thirteenth birthday.[28][29][30] A family tutor, Max Talmud, said that only a short time after he had given the twelve year old Einstein a geometry textbook, the boy "had worked through the whole book. He thereupon devoted himself to higher mathematics ... Soon the flight of his mathematical genius was so high I could not follow."[31] Einstein recorded that he had "mastered integral and differential calculus" while still just fourteen.[29] His love of algebra and geometry was so great that at twelve, he was already confident that nature could be understood as a "mathematical structure".[31] +

+
Studio photo of a boy seated in a relaxed posture and wearing a suit, posed in front of a backdrop of scenery.
Einstein in 1893, age 14
+ + + + + + + +

At thirteen, when his range of enthusiasms had broadened to include music and philosophy,[32] Talmud introduced Einstein to Kant\'s Critique of Pure Reason. Kant became his favorite philosopher; according to Talmud, "At the time he was still a child, only thirteen years old, yet Kant\'s works, incomprehensible to ordinary mortals, seemed to be clear to him."[31] +

+
Einstein's matriculation certificate at the age of 17. The heading translates as "The Education Committee of the Canton of Aargau". His scores were German 5, French 3, Italian 5, History 6, Geography 4, Algebra 6, Geometry 6, Descriptive Geometry 6, Physics 6, Chemistry 5, Natural History 5, Art Drawing 4, Technical Drawing 4. 6 = very good, 5 = good, 4 = sufficient, 3 = insufficient, 2 = poor, 1 = very poor.
Einstein\'s Matura certificate, 1896[note 2]
+

In 1895, at the age of sixteen, Einstein sat the entrance examination for the federal polytechnic school (later the Eidgenössische Technische Hochschule, ETH) in Zürich, Switzerland. He failed to reach the required standard in the general part of the test,[33] but performed with distinction in physics and mathematics.[34] On the advice of the polytechnic\'s principal, he completed his secondary education at the Argovian cantonal school (a gymnasium) in Aarau, Switzerland, graduating in 1896.[35] While lodging in Aarau with the family of Jost Winteler, he fell in love with Winteler\'s daughter, Marie. (His sister, Maja, later married Winteler\'s son Paul.[36]) +

In January 1896, with his father\'s approval, Einstein renounced his citizenship of the German Kingdom of Württemberg in order to avoid conscription into military service.[37] The Matura (graduation for the successful completion of higher secondary schooling) awarded to him in the September of that year acknowledged him to have performed well across most of the curriculum, allotting him a top grade of 6 for history, physics, algebra, geometry, and descriptive geometry.[38] At seventeen, he enrolled in the four-year mathematics and physics teaching diploma program at the federal polytechnic school. Marie Winteler, a year older than him, took up a teaching post in Olsberg, Switzerland.[36] +

The five other polytechnic school freshmen following the same course as Einstein included just one woman, a twenty year old Serbian, Mileva Marić. Over the next few years, the pair spent many hours discussing their shared interests and learning about topics in physics that the polytechnic school\'s lectures did not cover. In his letters to Marić, Einstein confessed that exploring science with her by his side was much more enjoyable than reading a textbook in solitude. Eventually the two students became not only friends but also lovers.[39] +

Historians of physics are divided on the question of the extent to which Marić contributed to the insights of Einstein\'s annus mirabilis publications. There is at least some evidence that he was influenced by her scientific ideas,[39][40][41] but there are scholars who doubt whether her impact on his thought was of any great significance at all.[42][43][44][45] +

+

Marriages, relationships and children

+
Albert Einstein and Mileva Marić Einstein, 1912
+
Albert Einstein and Elsa Einstein, 1930
+

Correspondence between Einstein and Marić, discovered and published in 1987, revealed that in early 1902, while Marić was visiting her parents in Novi Sad, she gave birth to a daughter, Lieserl. When Marić returned to Switzerland it was without the child, whose fate is uncertain. A letter of Einstein\'s that he wrote in September 1903 suggests that the girl was either given up for adoption or died of scarlet fever in infancy.[46][47] +

Einstein and Marić married in January 1903. In May 1904, their son Hans Albert was born in Bern, Switzerland. Their son Eduard was born in Zürich in July 1910. In letters that Einstein wrote to Marie Winteler in the months before Eduard\'s arrival, he described his love for his wife as "misguided" and mourned the "missed life" that he imagined he would have enjoyed if he had married Winteler instead: "I think of you in heartfelt love every spare minute and am so unhappy as only a man can be."[48] +

In 1912, Einstein entered into a relationship with Elsa Löwenthal, who was both his first cousin on his mother\'s side and his second cousin on his father\'s.[49][50][51] When Marić learned of his infidelity soon after moving to Berlin with him in April 1914, she returned to Zürich, taking Hans Albert and Eduard with her.[39] Einstein and Marić were granted a divorce on 14 February 1919 on the grounds of having lived apart for five years.[52][53] As part of the divorce settlement, Einstein agreed that if he were to win a Nobel Prize, he would give the money that he received to Marić; he won the prize two years later.[54] +

Einstein married Löwenthal in 1919.[55][56] In 1923, he began a relationship with a secretary named Betty Neumann, the niece of his close friend Hans Mühsam.[57][58][59][60] Löwenthal nevertheless remained loyal to him, accompanying him when he emigrated to the United States in 1933. In 1935, she was diagnosed with heart and kidney problems. She died in December 1936.[61] +

A volume of Einstein\'s letters released by Hebrew University of Jerusalem in 2006[62] added further names to the catalog of women with whom he was romantically involved. They included Margarete Lebach (a married Austrian),[63] Estella Katzenellenbogen (the rich owner of a florist business), Toni Mendel (a wealthy Jewish widow) and Ethel Michanowski (a Berlin socialite), with whom he spent time and from whom he accepted gifts while married to Löwenthal.[64][65] After being widowed, Einstein was briefly in a relationship with Margarita Konenkova, thought by some to be a Russian spy; her husband, the Russian sculptor Sergei Konenkov, created the bronze bust of Einstein at the Institute for Advanced Study at Princeton.[66][67] +

Following an episode of acute mental illness at about the age of twenty, Einstein\'s son Eduard was diagnosed with schizophrenia.[68] He spent the remainder of his life either in the care of his mother or in temporary confinement in an asylum. After her death, he was committed permanently to Burghölzli, the Psychiatric University Hospital in Zürich.[69] +

+

1902–1909: Assistant at the Swiss Patent Office

+

Einstein graduated from the federal polytechnic school in 1900, duly certified as competent to teach mathematics and physics.[70] His successful acquisition of Swiss citizenship in February 1901[71] was not followed by the usual sequel of conscription; the Swiss authorities deemed him medically unfit for military service. He found that Swiss schools too appeared to have no use for him, failing to offer him a teaching position despite the almost two years that he spent applying for one. Eventually it was with the help of Marcel Grossmann\'s father that he secured a post in Bern at the Swiss Patent Office,[72][73] as an assistant examiner – level III.[74][75] +

Patent applications that landed on Einstein\'s desk for his evaluation included ideas for a gravel sorter and an electric typewriter.[75] His employers were pleased enough with his work to make his position permanent in 1903, although they did not think that he should be promoted until he had "fully mastered machine technology".[76] It is conceivable that his labors at the patent office had a bearing on his development of his special theory of relativity. He arrived at his revolutionary ideas about space, time and light through thought experiments about the transmission of signals and the synchronization of clocks, matters which also figured in some of the inventions submitted to him for assessment.[13] +

In 1902, Einstein and some friends whom he had met in Bern formed a group that held regular meetings to discuss science and philosophy. Their choice of a name for their club, the Olympia Academy, was an ironic comment upon its far from Olympian status. Sometimes they were joined by Marić, who limited her participation in their proceedings to careful listening.[77] The thinkers whose works they reflected upon included Henri Poincaré, Ernst Mach and David Hume, all of whom significantly influenced Einstein\'s own subsequent ideas and beliefs.[78] +

+

1900–1905: First scientific papers

+
Cover image of the PhD dissertation of Albert Einstein
Einstein\'s 1905 dissertation, Eine neue Be­stimm­ung der Mol­e­kül­di­men­si­one ("A new deter­mi­na­tion of mo­lec­u­lar di­men­sions")
+

Einstein\'s first paper, "Folgerungen aus den Capillaritätserscheinungen" ("Conclusions drawn from the phenomena of capillarity"), in which he proposed a model of intermolecular attraction that he afterwards disavowed as worthless, was published in the journal Annalen der Physik in 1901.[79][80] His 24-page doctoral dissertation also addressed a topic in molecular physics. Titled "Eine neue Bestimmung der Moleküldimensionen" ("A New Determination of Molecular Dimensions") and dedicated to his friend Marcel Grossman, it was completed on 30 April 1905[81] and approved by Professor Alfred Kleiner of the University of Zurich three months later. (Einstein was formally awarded his PhD on 15 January 1906.)[81][82][83] Four other pieces of work that Einstein completed in 1905—his famous papers on the photoelectric effect, Brownian motion, his special theory of relativity and the equivalence of mass and energy—have led to the year being celebrated as an annus mirabilis for physics akin to 1666 (the year in which Isaac Newton experienced his greatest epiphanies). The publications deeply impressed Einstein\'s contemporaries.[84] +

+

1908–1933: Early academic career

+

Einstein\'s sabbatical as a civil servant approached its end in 1908, when he secured a junior teaching position at the University of Bern. In 1909, a lecture on relativistic electrodynamics that he gave at the University of Zurich, much admired by Alfred Kleiner, led to Zürich\'s luring him away from Bern with a newly created associate professorship.[85] Promotion to a full professorship followed in April 1911, when he accepted a chair at the German Charles-Ferdinand University in Prague, a move which required him to become an Austrian citizen of the Austro-Hungarian Empire.[86][87] His time in Prague saw him producing eleven research papers.[88] +

+
Head and shoulders shot of a young, moustached man with dark, curly hair wearing a plaid suit and vest, striped shirt, and a dark tie.
Einstein in 1904, age 25
Three young men in suits with high white collars and bow ties, sitting.
Olympia Academy founders: Conrad Habicht, Maurice Solovine, and Einstein
+

In July 1912, he returned to his alma mater, the ETH Zurich, to take up a chair in theoretical physics. His teaching activities there centred on thermodynamics and analytical mechanics, and his research interests included the molecular theory of heat, continuum mechanics and the development of a relativistic theory of gravitation. In his work on the latter topic, he was assisted by his friend, Marcel Grossmann, whose knowledge of the kind of mathematics required was greater than his own.[89] +

In the spring of 1913, two German visitors, Max Planck and Walther Nernst, called upon Einstein in Zürich in the hope of persuading him to relocate to Berlin.[90] They offered him membership of the Prussian Academy of Sciences, the directorship of the planned Kaiser Wilhelm Institute for Physics and a chair at the Humboldt University of Berlin that would allow him to pursue his research supported by a professorial salary but with no teaching duties to burden him.[50] Their invitation was all the more appealing to him because Berlin happened to be the home of his latest girlfriend, Elsa Löwenthal.[90] He duly joined the Academy on 24 +July 1913,[91] and moved into an apartment in the Berlin district of Dahlem on 1 April 1914.[50] He was installed in his Humboldt University position shortly thereafter.[91] +

The outbreak of the First World War in July 1914 marked the beginning of Einstein\'s gradual estrangement from the nation of his birth. When the "Manifesto of the Ninety-Three" was published in October 1914—a document signed by a host of prominent German thinkers that justified Germany\'s belligerence—Einstein was one of the few German intellectuals to distance himself from it and sign the alternative, eirenic "Manifesto to the Europeans" instead.[92][93] But this expression of his doubts about German policy did not prevent him from being elected to a two-year term as president of the German Physical Society in 1916.[94] And when the Kaiser Wilhelm Institute for Physics opened its doors the following year—its foundation delayed because of the war—Einstein was appointed its first director, just as Planck and Nernst had promised.[95] +

Einstein was elected a Foreign Member of the Royal Netherlands Academy of Arts and Sciences in 1920,[96] and a Foreign Member of the Royal Society in 1921. In 1922, he was awarded the 1921 Nobel Prize in Physics "for his services to Theoretical Physics, and especially for his discovery of the law of the photoelectric effect".[7] At this point some physicists still regarded the general theory of relativity sceptically, and the Nobel citation displayed a degree of doubt even about the work on photoelectricity that it acknowledged: it did not assent to Einstein\'s notion of the particulate nature of light, which only won over the entire scientific community when S. N. Bose derived the Planck spectrum in 1924. That same year, Einstein was elected an International Honorary Member of the American Academy of Arts and Sciences.[97] Britain\'s closest equivalent of the Nobel award, the Royal Society\'s Copley Medal, was not hung around Einstein\'s neck until 1925.[1] He was elected an International Member of the American Philosophical Society in 1930.[98] +

Einstein resigned from the Prussian Academy in March 1933. His accomplishments in Berlin had included the completion of the general theory of relativity, proving the Einstein–de Haas effect, contributing to the quantum theory of radiation, and the development of Bose–Einstein statistics.[50] +

+

1919: Putting general relativity to the test

+
The New York Times reported confirmation of the bending of light by gravitation after observations (made in Príncipe and Sobral) of the 29 May 1919 eclipse were presented to a joint meeting in London of the Royal Society and the Royal Astronomical Society on 6 November 1919.[99]
+

In 1907, Einstein reached a milestone on his long journey from his special theory of relativity to a new idea of gravitation with the formulation of his equivalence principle, which asserts that an observer in an infinitesimally small box falling freely in a gravitational field would be unable to find any evidence that the field exists. In 1911, he used the principle to estimate the amount by which a ray of light from a distant star would be bent by the gravitational pull of the Sun as it passed close to the Sun\'s photosphere (that is, the Sun\'s apparent surface). He reworked his calculation in 1913, having now found a way to model gravitation with the Riemann curvature tensor of a non-Euclidean four-dimensional spacetime. By the fall of 1915, his reimagining of the mathematics of gravitation in terms of Riemannian geometry was complete, and he applied his new theory not just to the behavior of the Sun as a gravitational lens but also to another astronomical phenomenon, the precession of the perihelion of Mercury (a slow drift in the point in Mercury\'s elliptical orbit at which it approaches the Sun most closely).[50][100] A total eclipse of the Sun that took place on 29 May 1919 provided an opportunity to put his theory of gravitational lensing to the test, and observations performed by Sir Arthur Eddington yielded results that were consistent with his calculations. Eddington\'s work was reported at length in newspapers around the world. On 7 November 1919, for example, the leading British newspaper, The Times, printed a banner headline that read: "Revolution in Science – New Theory of the Universe – Newtonian Ideas Overthrown".[101] +

+

1921–1923: Coming to terms with fame

+
Einstein\'s official portrait after receiving the 1921 Nobel Prize for Physics
+

With Eddington\'s eclipse observations widely reported not just in academic journals but by the popular press as well, Einstein became "perhaps the world\'s first celebrity scientist", a genius who had shattered a paradigm that had been basic to physicists\' understanding of the universe since the seventeenth century.[102] +

Einstein began his new life as an intellectual icon in America, where he arrived on 2 April 1921. He was welcomed to New York City by Mayor John Francis Hylan, and then spent three weeks giving lectures and attending receptions.[103] He spoke several times at Columbia University and Princeton, and in Washington, he visited the White House with representatives of the National Academy of Sciences. He returned to Europe via London, where he was the guest of the philosopher and statesman Viscount Haldane. He used his time in the British capital to meet several people prominent in British scientific, political or intellectual life, and to deliver a lecture at King\'s College.[104][105] In July 1921, he published an essay, "My First Impression of the U.S.A.", in which he sought to sketch the American character, much as had Alexis de Tocqueville in Democracy in America (1835).[106] He wrote of his transatlantic hosts in highly approving terms: "What strikes a visitor is the joyous, positive attitude to life ... The American is friendly, self-confident, optimistic, and without envy."[107] +

In 1922, Einstein\'s travels were to the old world rather than the new. He devoted six months to a tour of Asia that saw him speaking in Japan, Singapore and Sri Lanka (then known as Ceylon). After his first public lecture in Tokyo, he met Emperor Yoshihito and his wife at the Imperial Palace, with thousands of spectators thronging the streets in the hope of catching a glimpse of him. (In a letter to his sons, he wrote that Japanese people seemed to him to be generally modest, intelligent and considerate, and to have a true appreciation of art.[108] But his picture of them in his diary was less flattering: "[the] intellectual needs of this nation seem to be weaker than their artistic ones – natural disposition?" His journal also contains views of China and India which were uncomplimentary. Of Chinese people, he wrote that "even the children are spiritless and look obtuse... It would be a pity if these Chinese supplant all other races. For the likes of us the mere thought is unspeakably dreary".[109][110]) He was greeted with even greater enthusiasm on the last leg of his tour, in which he spent twelve days in Mandatory Palestine, newly entrusted to British rule by the League of Nations in the aftermath of the First World War. Sir Herbert Samuel, the British High Commissioner, welcomed him with a degree of ceremony normally only accorded to a visiting head of state, including a cannon salute. One reception held in his honor was stormed by people determined to hear him speak: he told them that he was happy that Jews were beginning to be recognized as a force in the world.[111] +

Einstein\'s decision to tour the eastern hemisphere in 1922 meant that he was unable to go to Stockholm in the December of that year to participate in the Nobel prize ceremony. His place at the traditional Nobel banquet was taken by a German diplomat, who gave a speech praising him not only as a physicist but also as a campaigner for peace.[112] A two week visit to Spain that he undertook in 1923 saw him collecting another award, a membership of the Spanish Academy of Sciences signified by a diploma handed to him by King Alfonso XIII. (His Spanish trip also gave him a chance to meet a fellow Nobel laureate, the neuroanatomist Santiago Ramón y Cajal.)[113] +

+

1922–1932: Serving the League of Nations

+
Einstein at a session of the International Committee on Intellectual Cooperation (League of Nations) of which he was a member from 1922 to 1932
+

From 1922 until 1932, with the exception of a few months in 1923 and 1924, Einstein was a member of the Geneva-based International Committee on Intellectual Cooperation of the League of Nations, a group set up by the League to encourage scientists, artists, scholars, teachers and other people engaged in the life of the mind to work more closely with their counterparts in other countries.[114][115] He was appointed as a German delegate rather than as a representative of Switzerland because of the machinations of two Catholic activists, Oskar Halecki and Giuseppe Motta. By persuading Secretary General Eric Drummond to deny Einstein the place on the committee reserved for a Swiss thinker, they created an opening for Gonzague de Reynold, who used his League of Nations position as a platform from which to promote traditional Catholic doctrine.[116] Einstein\'s former physics professor Hendrik Lorentz and the Polish chemist Marie Curie were also members of the committee.[117] +

+

1925: Touring South America

+

In March and April 1925, Einstein and his wife visited South America, where they spent about a week in Brazil, a week in Uruguay and a month in Argentina.[118] Their tour was suggested by Jorge Duclout (1856–1927) and Mauricio Nirenstein (1877–1935)[119] with the support of several Argentine scholars, including Julio Rey Pastor, Jakob Laub, and Leopoldo Lugones. and was financed primarily by the Council of the University of Buenos Aires and the Asociación Hebraica Argentina (Argentine Hebraic Association) with a smaller contribution from the Argentine-Germanic Cultural Institution.[120] +

+

1930–1931: Touring the US

+

In December 1930, Einstein began another significant sojourn in the United States, drawn back to the US by the offer of a two month research fellowship at the California Institute of Technology. Caltech supported him in his wish that he should not be exposed to quite as much attention from the media as he had experienced when visiting the US in 1921, and he therefore declined all the invitations to receive prizes or make speeches that his admirers poured down upon him. But he remained willing to allow his fans at least some of the time with him that they requested.[121] +

After arriving in New York City, Einstein was taken to various places and events, including Chinatown, a lunch with the editors of The New York Times, and a performance of Carmen at the Metropolitan Opera, where he was cheered by the audience on his arrival. During the days following, he was given the keys to the city by Mayor Jimmy Walker and met Nicholas Murray Butler, the president of Columbia University, who described Einstein as "the ruling monarch of the mind".[122] Harry Emerson Fosdick, pastor at New York\'s Riverside Church, gave Einstein a tour of the church and showed him a full-size statue that the church made of Einstein, standing at the entrance.[122] Also during his stay in New York, he joined a crowd of 15,000 people at Madison Square Garden during a Hanukkah celebration.[122] +

+
Einstein with Charlie Chaplin at the Hollywood premiere of Chaplin\'s City Lights, January 1931
+

Einstein next traveled to California, where he met Caltech president and Nobel laureate Robert A. Millikan. His friendship with Millikan was "awkward", as Millikan "had a penchant for patriotic militarism", where Einstein was a pronounced pacifist.[123] During an address to Caltech\'s students, Einstein noted that science was often inclined to do more harm than good.[124] +

This aversion to war also led Einstein to befriend author Upton Sinclair and film star Charlie Chaplin, both noted for their pacifism. Carl Laemmle, head of Universal Studios, gave Einstein a tour of his studio and introduced him to Chaplin. They had an instant rapport, with Chaplin inviting Einstein and his wife, Elsa, to his home for dinner. Chaplin said Einstein\'s outward persona, calm and gentle, seemed to conceal a "highly emotional temperament", from which came his "extraordinary intellectual energy".[125] +

Chaplin\'s film City Lights was to premiere a few days later in Hollywood, and Chaplin invited Einstein and Elsa to join him as his special guests. Walter Isaacson, Einstein\'s biographer, described this as "one of the most memorable scenes in the new era of celebrity".[124] Chaplin visited Einstein at his home on a later trip to Berlin and recalled his "modest little flat" and the piano at which he had begun writing his theory. Chaplin speculated that it was "possibly used as kindling wood by the Nazis".[126] +

+

1933: Emigration to the US

+
Cartoon of Einstein, who has shed his "Pacifism" wings, standing next to a pillar labeled "World Peace". He is rolling up his sleeves and holding a sword labeled "Preparedness".
Cartoon of Einstein after shedding his "pacifism" wings (Charles R. Macauley, c. 1933)
+

In February 1933, while on a visit to the United States, Einstein knew he could not return to Germany with the rise to power of the Nazis under Germany\'s new chancellor, Adolf Hitler.[127][128] +

While at American universities in early 1933, he undertook his third two-month visiting professorship at the California Institute of Technology in Pasadena. In February and March 1933, the Gestapo repeatedly raided his family\'s apartment in Berlin.[129] He and his wife Elsa returned to Europe in March, and during the trip, they learned that the German Reichstag had passed the Enabling Act on 23 March, transforming Hitler\'s government into a de facto legal dictatorship, and that they would not be able to proceed to Berlin. Later on, they heard that their cottage had been raided by the Nazis and Einstein\'s personal sailboat confiscated. Upon landing in Antwerp, Belgium on 28 March, Einstein immediately went to the German consulate and surrendered his passport, formally renouncing his German citizenship.[130] The Nazis later sold his boat and converted his cottage into a Hitler Youth camp.[131] +

+

Refugee status

+
Landing card for Einstein\'s 26 May 1933 arrival in Dover, England from Ostend, Belgium, enroute to Oxford
+

In April 1933, Einstein discovered that the new German government had passed laws barring Jews from holding any official positions, including teaching at universities.[130] Historian Gerald Holton describes how, with "virtually no audible protest being raised by their colleagues", thousands of Jewish scientists were suddenly forced to give up their university positions and their names were removed from the rolls of institutions where they were employed.[132] +

A month later, Einstein\'s works were among those targeted by the German Student Union in the Nazi book burnings, with Nazi propaganda minister Joseph Goebbels proclaiming, "Jewish intellectualism is dead."[130] One German magazine included him in a list of enemies of the German regime with the phrase, "not yet hanged", offering a $5,000 bounty on his head.[130][133] In a subsequent letter to physicist and friend Max Born, who had already emigrated from Germany to England, Einstein wrote, "... I must confess that the degree of their brutality and cowardice came as something of a surprise."[130] After moving to the US, he described the book burnings as a "spontaneous emotional outburst" by those who "shun popular enlightenment", and "more than anything else in the world, fear the influence of men of intellectual independence".[134] +

Einstein was now without a permanent home, unsure where he would live and work, and equally worried about the fate of countless other scientists still in Germany. Aided by the Academic Assistance Council, founded in April 1933 by British Liberal politician William Beveridge to help academics escape Nazi persecution, Einstein was able to leave Germany.[135] He rented a house in De Haan, Belgium, where he lived for a few months. In late July 1933, he visited England for about six weeks at the invitation of the British Member of Parliament Commander Oliver Locker-Lampson, who had become friends with him in the preceding years.[136] Locker-Lampson invited him to stay near his Cromer home in a secluded wooden cabin on Roughton Heath in the Parish of Roughton, Norfolk. To protect Einstein, Locker-Lampson had two bodyguards watch over him; a photo of them carrying shotguns and guarding Einstein was published in the Daily Herald on 24 July 1933.[137][138] +

+
Winston Churchill and Einstein at Chartwell House, 31 May 1933
+

Locker-Lampson took Einstein to meet Winston Churchill at his home, and later, Austen Chamberlain and former Prime Minister Lloyd George.[139] Einstein asked them to help bring Jewish scientists out of Germany. British historian Martin Gilbert notes that Churchill responded immediately, and sent his friend, physicist Frederick Lindemann, to Germany to seek out Jewish scientists and place them in British universities.[140] Churchill later observed that as a result of Germany having driven the Jews out, they had lowered their "technical standards" and put the Allies\' technology ahead of theirs.[140] +

Einstein later contacted leaders of other nations, including Turkey\'s Prime Minister, İsmet İnönü, to whom he wrote in September 1933 requesting placement of unemployed German-Jewish scientists. As a result of Einstein\'s letter, Jewish invitees to Turkey eventually totaled over "1,000 saved individuals".[141] +

Locker-Lampson also submitted a bill to parliament to extend British citizenship to Einstein, during which period Einstein made a number of public appearances describing the crisis brewing in Europe.[142] In one of his speeches he denounced Germany\'s treatment of Jews, while at the same time he introduced a bill promoting Jewish citizenship in Palestine, as they were being denied citizenship elsewhere.[143] In his speech he described Einstein as a "citizen of the world" who should be offered a temporary shelter in the UK.[note 3][144] Both bills failed, however, and Einstein then accepted an earlier offer from the Institute for Advanced Study, in Princeton, New Jersey, US, to become a resident scholar.[142] +

+

Resident scholar at the Institute for Advanced Study

+
Portrait of Einstein taken in 1935 at Princeton
+

On 3 October 1933, Einstein delivered a speech on the importance of academic freedom before a packed audience at the Royal Albert Hall in London, with The Times reporting he was wildly cheered throughout.[135] Four days later he returned to the US and took up a position at the Institute for Advanced Study,[142][145] noted for having become a refuge for scientists fleeing Nazi Germany.[146] At the time, most American universities, including Harvard, Princeton and Yale, had minimal or no Jewish faculty or students, as a result of their Jewish quotas, which lasted until the late 1940s.[146] +

Einstein was still undecided on his future. He had offers from several European universities, including Christ Church, Oxford, where he stayed for three short periods between May 1931 and June 1933 and was offered a five-year research fellowship (called a "studentship" at Christ Church),[147][148] but in 1935, he arrived at the decision to remain permanently in the United States and apply for citizenship.[142][149] +

Einstein\'s affiliation with the Institute for Advanced Study would last until his death in 1955.[150] He was one of the four first selected (along with John von Neumann, Kurt Gödel, and Hermann Weyl[151]) at the new Institute. He soon developed a close friendship with Gödel; the two would take long walks together discussing their work. Bruria Kaufman, his assistant, later became a physicist. During this period, Einstein tried to develop a unified field theory and to refute the accepted interpretation of quantum physics, both unsuccessfully. He lived in Princeton at his home from 1935 onwards. The Albert Einstein House was made a National Historic Landmark in 1976. +

+

World War II and the Manhattan Project

+ +
Marble bust of Einstein at the Deutsches Museum in Munich
+

In 1939, a group of Hungarian scientists that included émigré physicist Leó Szilárd attempted to alert Washington to ongoing Nazi atomic bomb research. The group\'s warnings were discounted. Einstein and Szilárd, along with other refugees such as Edward Teller and Eugene Wigner, "regarded it as their responsibility to alert Americans to the possibility that German scientists might win the race to build an atomic bomb, and to warn that Hitler would be more than willing to resort to such a weapon."[152][153] To make certain the US was aware of the danger, in July 1939, a few months before the beginning of World War II in Europe, Szilárd and Wigner visited Einstein to explain the possibility of atomic bombs, which Einstein, a pacifist, said he had never considered.[154] He was asked to lend his support by writing a letter, with Szilárd, to President Roosevelt, recommending the US pay attention and engage in its own nuclear weapons research. +

The letter is believed to be "arguably the key stimulus for the U.S. adoption of serious investigations into nuclear weapons on the eve of the U.S. entry into World War II".[155] In addition to the letter, Einstein used his connections with the Belgian royal family[156] and the Belgian queen mother to get access with a personal envoy to the White House\'s Oval Office. Some say that as a result of Einstein\'s letter and his meetings with Roosevelt, the US entered the "race" to develop the bomb, drawing on its "immense material, financial, and scientific resources" to initiate the Manhattan Project. +

For Einstein, "war was a disease ... [and] he called for resistance to war." By signing the letter to Roosevelt, some argue he went against his pacifist principles.[157] In 1954, a year before his death, Einstein said to his old friend, Linus Pauling, "I made one great mistake in my life—when I signed the letter to President Roosevelt recommending that atom bombs be made; but there was some justification—the danger that the Germans would make them ..."[158] In 1955, Einstein and ten other intellectuals and scientists, including British philosopher Bertrand Russell, signed a manifesto highlighting the danger of nuclear weapons.[159] In 1960 Einstein was included posthumously as a charter member of the World Academy of Art and Science (WAAS),[160] an organization founded by distinguished scientists and intellectuals who committed themselves to the responsible and ethical advances of science, particularly in light of the development of nuclear weapons. +

+

US citizenship

+
Einstein accepting a US citizenship certificate from judge Phillip Forman
+

Einstein became an American citizen in 1940. Not long after settling into his career at the Institute for Advanced Study in Princeton, New Jersey, he expressed his appreciation of the meritocracy in American culture compared to Europe. He recognized the "right of individuals to say and think what they pleased" without social barriers. As a result, individuals were encouraged, he said, to be more creative, a trait he valued from his early education.[161] +

Einstein joined the National Association for the Advancement of Colored People (NAACP) in Princeton, where he campaigned for the civil rights of African Americans. He considered racism America\'s "worst disease",[133][162] seeing it as "handed down from one generation to the next".[163] As part of his involvement, he corresponded with civil rights activist W. E. B. Du Bois and was prepared to testify on his behalf during his trial as an alleged foreign agent in 1951.[164] When Einstein offered to be a character witness for Du Bois, the judge decided to drop the case.[165] +

In 1946, Einstein visited Lincoln University in Pennsylvania, a historically black college, where he was awarded an honorary degree. Lincoln was the first university in the United States to grant college degrees to African Americans; alumni include Langston Hughes and Thurgood Marshall. Einstein gave a speech about racism in America, adding, "I do not intend to be quiet about it."[166] A resident of Princeton recalls that Einstein had once paid the college tuition for a black student.[165] Einstein has said, "Being a Jew myself, perhaps I can understand and empathize with how black people feel as victims of discrimination".[162] +

+

Personal views

+

Political views

+ +
Casual group shot of four men and two women standing on a brick pavement.
Albert Einstein and Elsa Einstein arriving in New York in 1921. Accompanying them are Zionist leaders Chaim Weizmann (future president of Israel), Weizmann\'s wife Vera Weizmann, Menahem Ussishkin, and Ben-Zion Mossinson.
+

In 1918, Einstein was one of the signatories of the founding proclamation of the German Democratic Party, a liberal party.[167][168] Later in his life, Einstein\'s political view was in favor of socialism and critical of capitalism, which he detailed in his essays such as "Why Socialism?".[169][170] His opinions on the Bolsheviks also changed with time. In 1925, he criticized them for not having a "well-regulated system of government" and called their rule a "regime of terror and a tragedy in human history". He later adopted a more moderated view, criticizing their methods but praising them, which is shown by his 1929 remark on Vladimir Lenin: +

+

In Lenin I honor a man, who in total sacrifice of his own person has committed his entire energy to realizing social justice. I do not find his methods advisable. One thing is certain, however: men like him are the guardians and renewers of mankind\'s conscience.[171]

+

Einstein offered and was called on to give judgments and opinions on matters often unrelated to theoretical physics or mathematics.[142] He strongly advocated the idea of a democratic global government that would check the power of nation-states in the framework of a world federation.[172] He wrote "I advocate world government because I am convinced that there is no other possible way of eliminating the most terrible danger in which man has ever found himself."[173] The FBI created a secret dossier on Einstein in 1932; by the time of his death, it was 1,427 pages long.[174] +

Einstein was deeply impressed by Mahatma Gandhi, with whom he corresponded. He described Gandhi as "a role model for the generations to come".[175] The initial connection was established on 27 September 1931, when Wilfrid Israel took his Indian guest V. A. Sundaram to meet his friend Einstein at his summer home in the town of Caputh. Sundaram was Gandhi\'s disciple and special envoy, whom Wilfrid Israel met while visiting India and visiting the Indian leader\'s home in 1925. During the visit, Einstein wrote a short letter to Gandhi that was delivered to him through his envoy, and Gandhi responded quickly with his own letter. Although in the end Einstein and Gandhi were unable to meet as they had hoped, the direct connection between them was established through Wilfrid Israel.[176] +

+

Relationship with Zionism

+ +
Einstein in 1947
+

Einstein was a figurehead leader in the establishment of the Hebrew University of Jerusalem,[177] which opened in 1925. Earlier, in 1921, he was asked by the biochemist and president of the World Zionist Organization, Chaim Weizmann, to help raise funds for the planned university.[178] He made suggestions for the creation of an Institute of Agriculture, a Chemical Institute and an Institute of Microbiology in order to fight the various ongoing epidemics such as malaria, which he called an "evil" that was undermining a third of the country\'s development.[179] He also promoted the establishment of an Oriental Studies Institute, to include language courses given in both Hebrew and Arabic.[180] +

Einstein referred to himself as a member of the Zionist movement[181] and supported the right of Jewish people to return to Palestine, but favored a “free, bi-national Palestine” in which Jews and Arabs would share sovereignty.[182] In a 1945 letter to Judge Jerome Frank, Einstein wrote, “Zionism has also a very good influence on the Jewish people…Jews who have a vivid feeling of Jewish national solidarity are much better equipped to overcome with dignity all the dangers and hardships which we have to face.” He continued, however, “I dislike nationalism very much — even Jewish nationalism. But our own national solidarity is forced upon us by a hostile world, and not the aggressive feelings which we connect with the word ‘Nationalism’.”[182] In a 1946 letter to Maurice Dunay, he wrote, “I am in favor of Palestine being developed as a Jewish Homeland, but not as a separate state.”[182] +

Upon the death of Israeli president Weizmann in November 1952, Prime Minister David Ben-Gurion offered Einstein the largely ceremonial position of President of Israel at the urging of Ezriel Carlebach.[183][184] The offer was presented by Israel\'s ambassador in Washington, Abba Eban, who explained that the offer "embodies the deepest respect which the Jewish people can repose in any of its sons".[185] Einstein wrote that he was "deeply moved", but "at once saddened and ashamed" that he could not accept it.[185] +

+

Religious and philosophical views

+
Opening of Einstein\'s speech (11 April 1943) for the United Jewish Appeal (recording by Radio Universidad Nacional de La Plata, Argentina)
"Ladies (coughs) and gentlemen, our age is proud of the progress it has made in man\'s intellectual development. The search and striving for truth and knowledge is one of the highest of man\'s qualities ..."
+ +

Einstein expounded his spiritual outlook in a wide array of writings and interviews.[186] He said he had sympathy for the impersonal pantheistic God of Baruch Spinoza\'s philosophy.[187] He did not believe in a personal god who concerns himself with fates and actions of human beings, a view which he described as naïve.[188] He clarified, however, that "I am not an atheist",[189] preferring to call himself an agnostic,[190][191] or a "deeply religious nonbeliever".[188] When asked if he believed in an afterlife, Einstein replied, "No. And one life is enough for me."[192] +

Einstein was primarily affiliated with non-religious humanist and Ethical Culture groups in both the UK and US. He served on the advisory board of the First Humanist Society of New York,[193] and was an honorary associate of the Rationalist Association, which publishes New Humanist in Britain. For the 75th anniversary of the New York Society for Ethical Culture, he stated that the idea of Ethical Culture embodied his personal conception of what is most valuable and enduring in religious idealism. He observed, "Without \'ethical culture\' there is no salvation for humanity."[194] +

+In a German-language letter to philosopher Eric Gutkind, dated 3 January 1954, Einstein wrote:

The word God is for me nothing more than the expression and product of human weaknesses, the Bible a collection of honorable, but still primitive legends which are nevertheless pretty childish. No interpretation no matter how subtle can (for me) change this. ... For me the Jewish religion like all other religions is an incarnation of the most childish superstitions. And the Jewish people to whom I gladly belong and with whose mentality I have a deep affinity have no different quality for me than all other people. ... I cannot see anything \'chosen\' about them.[195]

+Einstein had been sympathetic toward vegetarianism for a long time. In a letter in 1930 to Hermann Huth, vice-president of the German Vegetarian Federation (Deutsche Vegetarier-Bund), he wrote:

Although I have been prevented by outward circumstances from observing a strictly vegetarian diet, I have long been an adherent to the cause in principle. Besides agreeing with the aims of vegetarianism for aesthetic and moral reasons, it is my view that a vegetarian manner of living by its purely physical effect on the human temperament would most beneficially influence the lot of mankind.[196]

+

He became a vegetarian himself only during the last part of his life. In March 1954 he wrote in a letter: "So I am living without fats, without meat, without fish, but am feeling quite well this way. It almost seems to me that man was not born to be a carnivore."[197] +

+

Love of music

+
Einstein playing the violin (image published in 1927)
+

Einstein developed an appreciation for music at an early age. In his late journals he wrote: +

+

If I were not a physicist, I would probably be a musician. I often think in music. I live my daydreams in music. I see my life in terms of music ... I get most joy in life out of music.[198][199]

+

His mother played the piano reasonably well and wanted her son to learn the violin, not only to instill in him a love of music but also to help him assimilate into German culture. According to conductor Leon Botstein, Einstein began playing when he was 5. However, he did not enjoy it at that age.[200] +

When he turned 13, he discovered the violin sonatas of Mozart, whereupon he became enamored of Mozart\'s compositions and studied music more willingly. Einstein taught himself to play without "ever practicing systematically". He said that "love is a better teacher than a sense of duty".[200] At the age of 17, he was heard by a school examiner in Aarau while playing Beethoven\'s violin sonatas. The examiner stated afterward that his playing was "remarkable and revealing of \'great insight\'". What struck the examiner, writes Botstein, was that Einstein "displayed a deep love of the music, a quality that was and remains in short supply. Music possessed an unusual meaning for this student."[200] +

Music took on a pivotal and permanent role in Einstein\'s life from that period on. Although the idea of becoming a professional musician himself was not on his mind at any time, among those with whom Einstein played chamber music were a few professionals, including Kurt Appelbaum, and he performed for private audiences and friends. Chamber music had also become a regular part of his social life while living in Bern, Zürich, and Berlin, where he played with Max Planck and his son, among others. He is sometimes erroneously credited as the editor of the 1937 edition of the Köchel catalog of Mozart\'s work; that edition was prepared by Alfred Einstein, who may have been a distant relation.[201][202] +

In 1931, while engaged in research at the California Institute of Technology, he visited the Zoellner family conservatory in Los Angeles, where he played some of Beethoven and Mozart\'s works with members of the Zoellner Quartet.[203][204] Near the end of his life, when the young Juilliard Quartet visited him in Princeton, he played his violin with them, and the quartet was "impressed by Einstein\'s level of coordination and intonation".[200] +

+

Death

+

On 17 April 1955, Einstein experienced internal bleeding caused by the rupture of an abdominal aortic aneurysm, which had previously been reinforced surgically by Rudolph Nissen in 1948.[205] He took the draft of a speech he was preparing for a television appearance commemorating the state of Israel\'s seventh anniversary with him to the hospital, but he did not live to complete it.[206] +

Einstein refused surgery, saying, "I want to go when I want. It is tasteless to prolong life artificially. I have done my share; it is time to go. I will do it elegantly."[207] He died in the Princeton Hospital early the next morning at the age of 76, having continued to work until near the end.[208] +

During the autopsy, the pathologist Thomas Stoltz Harvey removed Einstein\'s brain for preservation without the permission of his family, in the hope that the neuroscience of the future would be able to discover what made Einstein so intelligent.[209] Einstein\'s remains were cremated in Trenton, New Jersey,[210] and his ashes were scattered at an undisclosed location.[211][212] +

In a memorial lecture delivered on 13 December 1965 at UNESCO headquarters, nuclear physicist J. Robert Oppenheimer summarized his impression of Einstein as a person: "He was almost wholly without sophistication and wholly without worldliness ... There was always with him a wonderful purity at once childlike and profoundly stubborn."[213] +

Einstein bequeathed his personal archives, library, and intellectual assets to the Hebrew University of Jerusalem in Israel.[214] +

+

Scientific career

+

Throughout his life, Einstein published hundreds of books and articles.[19][215] He published more than 300 scientific papers and 150 non-scientific ones.[14][215] On 5 December 2014, universities and archives announced the release of Einstein\'s papers, comprising more than 30,000 unique documents.[216][217] Einstein\'s intellectual achievements and originality have made the word "Einstein" synonymous with "genius".[18] In addition to the work he did by himself he also collaborated with other scientists on additional projects including the Bose–Einstein statistics, the Einstein refrigerator and others.[218][219] +

+

1905 – Annus Mirabilis papers

+

The Annus Mirabilis papers are four articles pertaining to the photoelectric effect (which gave rise to quantum theory), Brownian motion, the special theory of relativity, and E = mc2 that Einstein published in the Annalen der Physik scientific journal in 1905. These four works contributed substantially to the foundation of modern physics and changed views on space, time, and matter. The four papers are: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Title (translated)Area of focusReceivedPublishedSignificance +
"On a Heuristic Viewpoint Concerning the Production and Transformation of Light"[220]Photoelectric effect18 March9 JuneResolved an unsolved puzzle by suggesting that energy is exchanged only in discrete amounts (quanta).[221] This idea was pivotal to the early development of quantum theory.[222] +
"On the Motion of Small Particles Suspended in a Stationary Liquid, as Required by the Molecular Kinetic Theory of Heat"[223]Brownian motion11 May18 JulyExplained empirical evidence for the atomic theory, supporting the application of statistical physics. +
"On the Electrodynamics of Moving Bodies"[224]Special relativity30 June26 SeptemberReconciled Maxwell\'s equations for electricity and magnetism with the laws of mechanics by introducing changes to mechanics, resulting from analysis based on empirical evidence that the speed of light is independent of the motion of the observer.[225] Discredited the concept of a "luminiferous ether".[226] +
"Does the Inertia of a Body Depend Upon Its Energy Content?"[227]Matter–energy equivalence27 September21 NovemberEquivalence of matter and energy, E = mc2, the existence of "rest energy", and the basis of nuclear energy. +
+

Statistical mechanics

+

Thermodynamic fluctuations and statistical physics

+ +

Einstein\'s first paper[79][228] submitted in 1900 to Annalen der Physik was on capillary attraction. It was published in 1901 with the title "Folgerungen aus den Capillaritätserscheinungen", which translates as "Conclusions from the capillarity phenomena". Two papers he published in 1902–1903 (thermodynamics) attempted to interpret atomic phenomena from a statistical point of view. These papers were the foundation for the 1905 paper on Brownian motion, which showed that Brownian movement can be construed as firm evidence that molecules exist. His research in 1903 and 1904 was mainly concerned with the effect of finite atomic size on diffusion phenomena.[228] +

+

Theory of critical opalescence

+ +

Einstein returned to the problem of thermodynamic fluctuations, giving a treatment of the density variations in a fluid at its critical point. Ordinarily the density fluctuations are controlled by the second derivative of the free energy with respect to the density. At the critical point, this derivative is zero, leading to large fluctuations. The effect of density fluctuations is that light of all wavelengths is scattered, making the fluid look milky white. Einstein relates this to Rayleigh scattering, which is what happens when the fluctuation size is much smaller than the wavelength, and which explains why the sky is blue.[229] Einstein quantitatively derived critical opalescence from a treatment of density fluctuations, and demonstrated how both the effect and Rayleigh scattering originate from the atomistic constitution of matter. +

+

Special relativity

+ +

Einstein\'s "Zur Elektrodynamik bewegter Körper"[224] ("On the Electrodynamics of Moving Bodies") was received on 30 June 1905 and published 26 September of that same year. It reconciled conflicts between Maxwell\'s equations (the laws of electricity and magnetism) and the laws of Newtonian mechanics by introducing changes to the laws of mechanics.[230] Observationally, the effects of these changes are most apparent at high speeds (where objects are moving at speeds close to the speed of light). The theory developed in this paper later became known as Einstein\'s special theory of relativity. +

This paper predicted that, when measured in the frame of a relatively moving observer, a clock carried by a moving body would appear to slow down, and the body itself would contract in its direction of motion. This paper also argued that the idea of a luminiferous aether—one of the leading theoretical entities in physics at the time—was superfluous.[note 4] +

In his paper on mass–energy equivalence, Einstein produced E = mc2 as a consequence of his special relativity equations.[231] Einstein\'s 1905 work on relativity remained controversial for many years, but was accepted by leading physicists, starting with Max Planck.[note 5][232] +

Einstein originally framed special relativity in terms of kinematics (the study of moving bodies). In 1908, Hermann Minkowski reinterpreted special relativity in geometric terms as a theory of spacetime. Einstein adopted Minkowski\'s formalism in his 1915 general theory of relativity.[233] +

+

General relativity

+

General relativity and the equivalence principle

+ + +
Black circle covering the sun, rays visible around it, in a dark sky.
Eddington\'s photograph of a solar eclipse
+

General relativity (GR) is a theory of gravitation that was developed by Einstein between 1907 and 1915. According to it, the observed gravitational attraction between masses results from the warping of spacetime by those masses. General relativity has developed into an essential tool in modern astrophysics; it provides the foundation for the current understanding of black holes, regions of space where gravitational attraction is so strong that not even light can escape.[234] +

As Einstein later said, the reason for the development of general relativity was that the preference of inertial motions within special relativity was unsatisfactory, while a theory which from the outset prefers no state of motion (even accelerated ones) should appear more satisfactory.[235] Consequently, in 1907 he published an article on acceleration under special relativity. In that article titled "On the Relativity Principle and the Conclusions Drawn from It", he argued that free fall is really inertial motion, and that for a free-falling observer the rules of special relativity must apply. This argument is called the equivalence principle. In the same article, Einstein also predicted the phenomena of gravitational time dilation, gravitational redshift and gravitational lensing.[236][237] +

In 1911, Einstein published another article "On the Influence of Gravitation on the Propagation of Light" expanding on the 1907 article, in which he estimated the amount of deflection of light by massive bodies. Thus, the theoretical prediction of general relativity could for the first time be tested experimentally.[238] +

+

Gravitational waves

+

In 1916, Einstein predicted gravitational waves,[239][240] ripples in the curvature of spacetime which propagate as waves, traveling outward from the source, transporting energy as gravitational radiation. The existence of gravitational waves is possible under general relativity due to its Lorentz invariance which brings the concept of a finite speed of propagation of the physical interactions of gravity with it. By contrast, gravitational waves cannot exist in the Newtonian theory of gravitation, which postulates that the physical interactions of gravity propagate at infinite speed. +

The first, indirect, detection of gravitational waves came in the 1970s through observation of a pair of closely orbiting neutron stars, PSR B1913+16.[241] The explanation for the decay in their orbital period was that they were emitting gravitational waves.[241][242] Einstein\'s prediction was confirmed on 11 February 2016, when researchers at LIGO published the first observation of gravitational waves,[243] detected on Earth on 14 September 2015, nearly one hundred years after the prediction.[241][244][245][246][247] +

+

Hole argument and Entwurf theory

+

While developing general relativity, Einstein became confused about the gauge invariance in the theory. He formulated an argument that led him to conclude that a general relativistic field theory is impossible. He gave up looking for fully generally covariant tensor equations and searched for equations that would be invariant under general linear transformations only.[248] +

In June 1913, the Entwurf (\'draft\') theory was the result of these investigations. As its name suggests, it was a sketch of a theory, less elegant and more difficult than general relativity, with the equations of motion supplemented by additional gauge fixing conditions. After more than two years of intensive work, Einstein realized that the hole argument was mistaken[249] and abandoned the theory in November 1915. +

+

Physical cosmology

+ +
Robert A. Millikan, Georges Lemaître, and Einstein at the California Institute of Technology in January 1933
+

In 1917, Einstein applied the general theory of relativity to the structure of the universe as a whole.[250] He discovered that the general field equations predicted a universe that was dynamic, either contracting or expanding. As observational evidence for a dynamic universe was lacking at the time, Einstein introduced a new term, the cosmological constant, into the field equations, in order to allow the theory to predict a static universe. The modified field equations predicted a static universe of closed curvature, in accordance with Einstein\'s understanding of Mach\'s principle in these years. This model became known as the Einstein World or Einstein\'s static universe.[251][252] +

Following the discovery of the recession of the galaxies by Edwin Hubble in 1929, Einstein abandoned his static model of the universe, and proposed two dynamic models of the cosmos, the Friedmann–Einstein universe of 1931[253][254] and the Einstein–de Sitter universe of 1932.[255][256] In each of these models, Einstein discarded the cosmological constant, claiming that it was "in any case theoretically unsatisfactory".[253][254][257] +

In many Einstein biographies, it is claimed that Einstein referred to the cosmological constant in later years as his "biggest blunder", based on a letter George Gamow claimed to have received from him. The astrophysicist Mario Livio has cast doubt on this claim.[258] +

In late 2013, a team led by the Irish physicist Cormac O\'Raifeartaigh discovered evidence that, shortly after learning of Hubble\'s observations of the recession of the galaxies, Einstein considered a steady-state model of the universe.[259][260] In a hitherto overlooked manuscript, apparently written in early 1931, Einstein explored a model of the expanding universe in which the density of matter remains constant due to a continuous creation of matter, a process that he associated with the cosmological constant.[261][262] As he stated in the paper, "In what follows, I would like to draw attention to a solution to equation (1) that can account for Hubbel\'s [sic] facts, and in which the density is constant over time" ... "If one considers a physically bounded volume, particles of matter will be continually leaving it. For the density to remain constant, new particles of matter must be continually formed in the volume from space." +

It thus appears that Einstein considered a steady-state model of the expanding universe many years before Hoyle, Bondi and Gold.[263][264] However, Einstein\'s steady-state model contained a fundamental flaw and he quickly abandoned the idea.[261][262][265] +

+

Energy momentum pseudotensor

+ +

General relativity includes a dynamical spacetime, so it is difficult to see how to identify the conserved energy and momentum. Noether\'s theorem allows these quantities to be determined from a Lagrangian with translation invariance, but general covariance makes translation invariance into something of a gauge symmetry. The energy and momentum derived within general relativity by Noether\'s prescriptions do not make a real tensor for this reason.[266] +

Einstein argued that this is true for a fundamental reason: the gravitational field could be made to vanish by a choice of coordinates. He maintained that the non-covariant energy momentum pseudotensor was, in fact, the best description of the energy momentum distribution in a gravitational field. While the use of non-covariant objects like pseudotensors was criticized by Erwin Schrödinger and others, Einstein\'s approach has been echoed by physicists including Lev Landau and Evgeny Lifshitz.[267] +

+

Wormholes

+

In 1935, Einstein collaborated with Nathan Rosen to produce a model of a wormhole, often called Einstein–Rosen bridges.[268][269] His motivation was to model elementary particles with charge as a solution of gravitational field equations, in line with the program outlined in the paper "Do Gravitational Fields play an Important Role in the Constitution of the Elementary Particles?". These solutions cut and pasted Schwarzschild black holes to make a bridge between two patches. Because these solutions included spacetime curvature without the presence of a physical body, Einstein and Rosen suggested that they could provide the beginnings of a theory that avoided the notion of point particles. However, it was later found that Einstein–Rosen bridges are not stable.[270] +

+

Einstein–Cartan theory

+ +
Einstein, sitting at a table, looks up from the papers he is reading and into the camera.
Einstein at his office, University of Berlin, 1920

In order to incorporate spinning point particles into general relativity, the affine connection needed to be generalized to include an antisymmetric part, called the torsion. This modification was made by Einstein and Cartan in the 1920s. +

Equations of motion

+ +

In general relativity, gravitational force is reimagined as curvature of spacetime. A curved path like an orbit is not the result of a force deflecting a body from an ideal straight-line path, but rather the body\'s attempt to fall freely through a background that is itself curved by the presence of other masses. A remark by John Archibald Wheeler that has become proverbial among physicists summarizes the theory: "Spacetime tells matter how to move; matter tells spacetime how to curve."[271][272] The Einstein field equations cover the latter aspect of the theory, relating the curvature of spacetime to the distribution of matter and energy. The geodesic equation covers the former aspect, stating that freely falling bodies follow lines that are as straight as possible in a curved spacetime. Einstein regarded this as an "independent fundamental assumption" that had to be postulated in addition to the field equations in order to complete the theory. Believing this to be a shortcoming in how general relativity was originally presented, he wished to derive it from the field equations themselves. Since the equations of general relativity are non-linear, a lump of energy made out of pure gravitational fields, like a black hole, would move on a trajectory which is determined by the Einstein field equations themselves, not by a new law. Accordingly, Einstein proposed that the field equations would determine the path of a singular solution, like a black hole, to be a geodesic. Both physicists and philosophers have often repeated the assertion that the geodesic equation can be obtained from applying the field equations to the motion of a gravitational singularity, but this claim remains disputed.[273][274] +

+

Old quantum theory

+ +

Photons and energy quanta

+
The photoelectric effect. Incoming photons on the left strike a metal plate (bottom), and eject electrons, depicted as flying off to the right.
+

In a 1905 paper,[220] Einstein postulated that light itself consists of localized particles (quanta). Einstein\'s light quanta were nearly universally rejected by all physicists, including Max Planck and Niels Bohr. This idea only became universally accepted in 1919, with Robert Millikan\'s detailed experiments on the photoelectric effect, and with the measurement of Compton scattering. +

Einstein concluded that each wave of frequency f is associated with a collection of photons with energy hf each, where h is the Planck constant. He did not say much more, because he was not sure how the particles were related to the wave. But he did suggest that this idea would explain certain experimental results, notably the photoelectric effect.[220] +

+

Quantized atomic vibrations

+ +

In 1907, Einstein proposed a model of matter where each atom in a lattice structure is an independent harmonic oscillator. In the Einstein model, each atom oscillates independently—a series of equally spaced quantized states for each oscillator. Einstein was aware that getting the frequency of the actual oscillations would be difficult, but he nevertheless proposed this theory because it was a particularly clear demonstration that quantum mechanics could solve the specific heat problem in classical mechanics. Peter Debye refined this model.[275] +

+

Bose–Einstein statistics

+ +

In 1924, Einstein received a description of a statistical model from Indian physicist Satyendra Nath Bose, based on a counting method that assumed that light could be understood as a gas of indistinguishable particles. Einstein noted that Bose\'s statistics applied to some atoms as well as to the proposed light particles, and submitted his translation of Bose\'s paper to the Zeitschrift für Physik. Einstein also published his own articles describing the model and its implications, among them the Bose–Einstein condensate phenomenon that some particulates should appear at very low temperatures.[276] It was not until 1995 that the first such condensate was produced experimentally by Eric Allin Cornell and Carl Wieman using ultra-cooling equipment built at the NISTJILA laboratory at the University of Colorado at Boulder.[277] Bose–Einstein statistics are now used to describe the behaviors of any assembly of bosons. Einstein\'s sketches for this project may be seen in the Einstein Archive in the library of the Leiden University.[218] +

+

Wave–particle duality

+
Einstein in 1921, photo by Harris & Ewing Studio
+

Although the patent office promoted Einstein to Technical Examiner Second Class in 1906, he had not given up on academia. In 1908, he became a Privatdozent at the University of Bern.[278] In "Über die Entwicklung unserer Anschauungen über das Wesen und die Konstitution der Strahlung" ("The Development of our Views on the Composition and Essence of Radiation"), on the quantization of light, and in an earlier 1909 paper, Einstein showed that Max Planck\'s energy quanta must have well-defined momenta and act in some respects as independent, point-like particles. This paper introduced the photon concept (although the name photon was introduced later by Gilbert N. Lewis in 1926) and inspired the notion of wave–particle duality in quantum mechanics. Einstein saw this wave–particle duality in radiation as concrete evidence for his conviction that physics needed a new, unified foundation. +

+

Zero-point energy

+

In a series of works completed from 1911 to 1913, Planck reformulated his 1900 quantum theory and introduced the idea of zero-point energy in his "second quantum theory". Soon, this idea attracted the attention of Einstein and his assistant Otto Stern. Assuming the energy of rotating diatomic molecules contains zero-point energy, they then compared the theoretical specific heat of hydrogen gas with the experimental data. The numbers matched nicely. However, after publishing the findings, they promptly withdrew their support, because they no longer had confidence in the correctness of the idea of zero-point energy.[279] +

+

Stimulated emission

+

In 1917, at the height of his work on relativity, Einstein published an article in Physikalische Zeitschrift that proposed the possibility of stimulated emission, the physical process that makes possible the maser and the laser.[280] +This article showed that the statistics of absorption and emission of light would only be consistent with Planck\'s distribution law if the emission of light into a mode with n photons would be enhanced statistically compared to the emission of light into an empty mode. This paper was enormously influential in the later development of quantum mechanics, because it was the first paper to show that the statistics of atomic transitions had simple laws.[281] +

+

Matter waves

+

Einstein discovered Louis de Broglie\'s work and supported his ideas, which were received skeptically at first. In another major paper from this era, Einstein observed that de Broglie waves could explain the quantization rules of Bohr and Sommerfeld. This paper would inspire Schrödinger\'s work of 1926.[282][283] +

+

Quantum mechanics

+

Einstein\'s objections to quantum mechanics

+
Newspaper headline on 4 May 1935
+

Einstein played a major role in developing quantum theory, beginning with his 1905 paper on the photoelectric effect. However, he became displeased with modern quantum mechanics as it had evolved after 1925, despite its acceptance by other physicists. He was skeptical that the randomness of quantum mechanics was fundamental rather than the result of determinism, stating that God "is not playing at dice".[284] Until the end of his life, he continued to maintain that quantum mechanics was incomplete.[285] +

+

Bohr versus Einstein

+ +
Two men sitting, looking relaxed. A dark-haired Bohr is talking while Einstein looks skeptical.
Einstein and Niels Bohr, 1925

The Bohr–Einstein debates were a series of public disputes about quantum mechanics between Einstein and Niels Bohr, who were two of its founders. Their debates are remembered because of their importance to the philosophy of science.[286][287][288] Their debates would influence later interpretations of quantum mechanics. +

Einstein–Podolsky–Rosen paradox

+ +

Einstein never fully accepted quantum mechanics. While he recognized that it made correct predictions, he believed a more fundamental description of nature must be possible. Over the years he presented multiple arguments to this effect, but the one he preferred most dated to a debate with Bohr in 1930. Einstein suggested a thought experiment in which two objects are allowed to interact and then moved apart a great distance from each other. The quantum-mechanical description of the two objects is a mathematical entity known as a wavefunction. If the wavefunction that describes the two objects before their interaction is given, then the Schrödinger equation provides the wavefunction that describes them after their interaction. But because of what would later be called quantum entanglement, measuring one object would lead to an instantaneous change of the wavefunction describing the other object, no matter how far away it is. Moreover, the choice of which measurement to perform upon the first object would affect what wavefunction could result for the second object. Einstein reasoned that no influence could propagate from the first object to the second instantaneously fast. Indeed, he argued, physics depends on being able to tell one thing apart from another, and such instantaneous influences would call that into question. Because the true "physical condition" of the second object could not be immediately altered by an action done to the first, Einstein concluded, the wavefunction could not be that true physical condition, only an incomplete description of it.[289][290] +

A more famous version of this argument came in 1935, when Einstein published a paper with Boris Podolsky and Nathan Rosen that laid out what would become known as the EPR paradox.[291] In this thought experiment, two particles interact in such a way that the wavefunction describing them is entangled. Then, no matter how far the two particles were separated, a precise position measurement on one particle would imply the ability to predict, perfectly, the result of measuring the position of the other particle. Likewise, a precise momentum measurement of one particle would result in an equally precise prediction for of the momentum of the other particle, without needing to disturb the other particle in any way. They argued that no action taken on the first particle could instantaneously affect the other, since this would involve information being transmitted faster than light, which is forbidden by the theory of relativity. They invoked a principle, later known as the "EPR criterion of reality", positing that: "If, without in any way disturbing a system, we can predict with certainty (i.e., with probability equal to unity) the value of a physical quantity, then there exists an element of reality corresponding to that quantity." From this, they inferred that the second particle must have a definite value of both position and of momentum prior to either quantity being measured. But quantum mechanics considers these two observables incompatible and thus does not associate simultaneous values for both to any system. Einstein, Podolsky, and Rosen therefore concluded that quantum theory does not provide a complete description of reality.[292] +

In 1964, John Stewart Bell carried the analysis of quantum entanglement much further. He deduced that if measurements are performed independently on the two separated particles of an entangled pair, then the assumption that the outcomes depend upon hidden variables within each half implies a mathematical constraint on how the outcomes on the two measurements are correlated. This constraint would later be called a Bell inequality. Bell then showed that quantum physics predicts correlations that violate this inequality. Consequently, the only way that hidden variables could explain the predictions of quantum physics is if they are "nonlocal", which is to say that somehow the two particles are able to interact instantaneously no matter how widely they ever become separated.[293][294] Bell argued that because an explanation of quantum phenomena in terms of hidden variables would require nonlocality, the EPR paradox "is resolved in the way which Einstein would have liked least".[295] +

Despite this, and although Einstein personally found the argument in the EPR paper overly complicated,[289][290] that paper became among the most influential papers published in Physical Review. It is considered a centerpiece of the development of quantum information theory.[296] +

+

Unified field theory

+ +

Encouraged by his success with general relativity, Einstein sought an even more ambitious geometrical theory that would treat gravitation and electromagnetism as aspects of a single entity. In 1950, he described his unified field theory in a Scientific American article titled "On the Generalized Theory of Gravitation".[297] His attempt to find the most fundamental laws of nature won him praise but not success: a particularly conspicuous blemish of his model was that it did not accommodate the strong and weak nuclear forces, neither of which was well understood until many years after his death. Although most researchers now believe that Einstein\'s approach to unifying physics was mistaken, his goal of a theory of everything is one to which his successors still aspire.[298] +

+

Other investigations

+ +

Einstein conducted other investigations that were unsuccessful and abandoned. These pertain to force, superconductivity, and other research. +

+

Collaboration with other scientists

+
The 1927 Solvay Conference in Brussels, a gathering of the world\'s top physicists. Einstein is in the center.
+

In addition to longtime collaborators Leopold Infeld, Nathan Rosen, Peter Bergmann and others, Einstein also had some one-shot collaborations with various scientists. +

+

Einstein–de Haas experiment

+ +

In 1908, Owen Willans Richardson predicted that a change in the magnetic moment of a free body will cause this body to rotate. This effect is a consequence of the conservation of angular momentum and is strong enough to be observable in ferromagnetic materials.[299] Einstein and Wander Johannes de Haas published two papers in 1915 claiming the first experimental observation of the effect.[300][301] Measurements of this kind demonstrate that the phenomenon of magnetization is caused by the alignment (polarization) of the angular momenta of the electrons in the material along the axis of magnetization. These measurements also allow the separation of the two contributions to the magnetization: that which is associated with the spin and with the orbital motion of the electrons. The Einstein-de Haas experiment is the only experiment concived, realized and published by Albert Einstein himself. +

A complete original version of the Einstein-de Haas experimental equipment was donated by Geertruida de Haas-Lorentz, wife of de Haas and daughter of Lorentz, to the Ampère Museum in Lyon France in 1961 where it is currently on display. It was lost among the museum\'s holdings and was rediscovered in 2023.[302][303] +

+

Einstein as an inventor

+

In 1926, Einstein and his former student Leó Szilárd co-invented (and in 1930, patented) the Einstein refrigerator. This absorption refrigerator was then revolutionary for having no moving parts and using only heat as an input.[304] On 11 November 1930, U.S. patent 1,781,541 was awarded to Einstein and Leó Szilárd for the refrigerator. Their invention was not immediately put into commercial production, but the most promising of their patents were acquired by the Swedish company Electrolux.[note 6] +

Einstein also invented an electromagnetic pump,[306] sound reproduction device,[307] and several other household devices.[308] +

+

Non-scientific legacy

+
Left-right: Heinrich Goldschmidt, Einstein, Ole Colbjørnsen, Jørgen Vogt, and Ilse Einstein at a picnic in Oslo in 1920.
+

While traveling, Einstein wrote daily to his wife Elsa and adopted stepdaughters Margot and Ilse. The letters were included in the papers bequeathed to the Hebrew University of Jerusalem. Margot Einstein permitted the personal letters to be made available to the public, but requested that it not be done until twenty years after her death (she died in 1986[309]). Barbara Wolff, of the Hebrew University\'s Albert Einstein Archives, told the BBC that there are about 3,500 pages of private correspondence written between 1912 and 1955.[310] +

Einstein\'s right of publicity was litigated in 2015 in a federal district court in California. Although the court initially held that the right had expired,[311] that ruling was immediately appealed, and the decision was later vacated in its entirety. The underlying claims between the parties in that lawsuit were ultimately settled. The right is enforceable, and the Hebrew University of Jerusalem is the exclusive representative of that right.[312] Corbis, successor to The Roger Richman Agency, licenses the use of his name and associated imagery, as agent for the university.[313] +

Mount Einstein in the Chugach Mountains of Alaska was named in 1955. +

Mount Einstein in New Zealand\'s Paparoa Range was named after him in 1970 by the Department of Scientific and Industrial Research.[314] +

+

In popular culture

+ +
The famous image of Einstein taken by International News photographer Arthur Sasse in 1951
+

Einstein became one of the most famous scientific celebrities after the confirmation of his general theory of relativity in 1919.[315][316][317] Although most of the public had little understanding of his work, he was widely recognized and admired. In the period before World War II, The New Yorker published a vignette in their "The Talk of the Town" feature saying that Einstein was so well known in America that he would be stopped on the street by people wanting him to explain "that theory". Eventually he came to cope with unwanted enquirers by pretending to be someone else: "Pardon me, sorry! Always I am mistaken for Professor Einstein."[318] +

Einstein has been the subject of or inspiration for many novels, films, plays, and works of music.[319] He is a favorite model for depictions of absent-minded professors; his expressive face and distinctive hairstyle have been widely copied and exaggerated. Time magazine\'s Frederic Golden wrote that Einstein was "a cartoonist\'s dream come true".[320] +

Many popular quotations are often misattributed to him.[321][322] +

+

Awards and honors

+ +

Einstein received numerous awards and honors, and in 1922, he was awarded the 1921 Nobel Prize in Physics "for his services to Theoretical Physics, and especially for his discovery of the law of the photoelectric effect". None of the nominations in 1921 met the criteria set by Alfred Nobel, so the 1921 prize was carried forward and awarded to Einstein in 1922.[7] +

Einsteinium, a synthetic chemical element, was named in his honor in 1955, a few months after his death.[323] +

+

Publications

+

Scientific

+
+
+ +
+

Others

+
+ +
+

See also

+ +

Notes

+
+
    +
  1. ^ a b c d e Until 1913, German citizenship was acquired through citizenship in a constituent state (whose requirements varied); from 1913, uniform citizenship requirements were set at the national level. +
  2. +
  3. ^ Einstein\'s scores on his Matura certificate: German 5; French 3; Italian 5; History 6; Geography 4; Algebra 6; Geometry 6; Descriptive Geometry 6; Physics 6; Chemistry 5; Natural History 5; Art Drawing 4; Technical Drawing 4.
    Scale: 6 = very good, 5 = good, 4 = sufficient, 3 = insufficient, 2 = poor, 1 = very poor.
    +
  4. +
  5. ^ "Their leaders in Germany have not driven out her cut-throats and her blackguards. She has chosen the cream of her culture and has suppressed it. She has even turned upon her most glorious citizen, Albert Einstein, who is the supreme example of the selfless intellectual...The man, who, beyond all others, approximates a citizen of the world, is without a home. How proud we must be to offer him temporary shelter." +
  6. +
  7. ^ In his paper, Einstein wrote: "The introduction of a \'luminiferous æther\' will be proved to be superfluous in so far, as according to the conceptions which will be developed, we shall introduce neither a \'space absolutely at rest\' endowed with special properties, nor shall we associate a velocity-vector with a point in which electro-magnetic processes take place." +
  8. +
  9. ^ For a discussion of the reception of relativity theory around the world, and the different controversies it encountered, see the articles in Glick (1987). +
  10. +
  11. ^ In September 2008 it was reported that Malcolm McCulloch of Oxford University was heading a three-year project to develop more robust appliances that could be used in locales lacking electricity, and that his team had completed a prototype Einstein refrigerator. He was quoted as saying that improving the design and changing the types of gases used might allow the design\'s efficiency to be quadrupled.[305] +
  12. +
+

References

+
+
    +
  1. ^ a b c d Whittaker, E. (1 November 1955). "Albert Einstein. 1879–1955". Biographical Memoirs of Fellows of the Royal Society. 1: 37–67. doi:10.1098/rsbm.1955.0005. JSTOR 769242. +
  2. +
  3. ^ "The Gold Medal" (PDF). Royal Astronomical Society. Archived (PDF) from the original on 20 December 2021. Retrieved 20 December 2021. +
  4. +
  5. ^ "Membership directory". National Academy of Sciences. Archived from the original on 20 December 2021. Retrieved 20 December 2021. +
  6. +
  7. ^ Wells, John (3 April 2008). Longman Pronunciation Dictionary (3rd ed.). Pearson Longman. ISBN 978-1-4058-8118-0. +
  8. +
  9. ^ Yang, Fujia; Hamilton, Joseph H. (2010). Modern Atomic and Nuclear Physics. World Scientific. p. 274. ISBN 978-981-4277-16-7. +
  10. +
  11. ^ Bodanis, David (2000). E = mc2: A Biography of the World\'s Most Famous Equation. New York: Walker. +
  12. +
  13. ^ a b c "The Nobel Prize in Physics 1921". Nobel Prize. Archived from the original on 3 July 2018. Retrieved 11 July 2016. +
  14. +
  15. ^ Howard, Don A., ed. (2014) [First published 11 February 2004]. "Einstein\'s Philosophy of Science". Stanford Encyclopedia of Philosophy. The Metaphysics Research Lab, Center for the Study of Language and Information (CSLI), Stanford University. Archived from the original on 13 April 2021. Retrieved 4 February 2015. +
  16. +
  17. ^ Howard, Don A. (December 2005). "Albert Einstein as a Philosopher of Science" (PDF). Physics Today. 58 (12): 34–40. Bibcode:2005PhT....58l..34H. doi:10.1063/1.2169442. S2CID 170769196. Archived (PDF) from the original on 28 August 2015. Retrieved 8 March 2015 – via University of Notre Dame, Notre Dame, IN, author\'s personal webpage. +
  18. +
  19. ^ Levenson, Thomas (9 June 2017). "The Scientist and the Fascist". The Atlantic. Archived from the original on 12 May 2019. Retrieved 23 August 2018. +
  20. +
  21. ^ Paul S. Boyer; Melvyn Dubofsky (2001). The Oxford Companion to United States History. Oxford University Press. p. 218. ISBN 978-0-19-508209-8. +
  22. +
  23. ^ "Albert Einstein on nuclear weapons | Wise International". wiseinternational.org. Retrieved 23 October 2022. +
  24. +
  25. ^ a b Galison (2000), p. 377. +
  26. +
  27. ^ a b "Scientific Background on the Nobel Prize in Physics 2011. The accelerating universe" (PDF). Nobel Media AB. p. 2. Archived from the original (PDF) on 16 May 2012. Retrieved 4 January 2015. +
  28. +
  29. ^ Overbye, Dennis (24 November 2015). "A Century Ago, Einstein\'s Theory of Relativity Changed Everything". The New York Times. Archived from the original on 1 January 2022. Retrieved 24 November 2015. +
  30. +
  31. ^ Robinson, Andrew (30 April 2018). "Did Einstein really say that?". Nature. 557 (30): 30. Bibcode:2018Natur.557...30R. doi:10.1038/d41586-018-05004-4. S2CID 14013938. Archived from the original on 9 November 2020. Retrieved 21 February 2021. +
  32. +
  33. ^ "Physics: past, present, future". Physics World. 6 December 1999. Retrieved 1 August 2023. +
  34. +
  35. ^ a b "Result of WordNet Search for Einstein". 3.1. The Trustees of Princeton University. Archived from the original on 28 August 2015. Retrieved 4 January 2015. +
  36. +
  37. ^ a b c "Albert Einstein – Biography". Nobel Foundation. Archived from the original on 6 March 2007. Retrieved 7 March 2007. +
  38. +
  39. ^ "Albert Einstein (1879–1955)". Jewisth Virtual Library. Archived from the original on 9 March 2017. Retrieved 13 February 2021. +
  40. +
  41. ^ Isaacson, Walter (2009). "How Einstein Divided America\'s Jews". The Atlantic. Archived from the original on 26 January 2021. Retrieved 13 February 2021. +
  42. +
  43. ^ Stachel (2002), pp. 59–61. +
  44. +
  45. ^ Barry R. Parker (2003). Einstein: The Passions of a Scientist, Prometheus Books, p. 31 +
  46. +
  47. ^ University of Pavia. "Einstein, Albert". Museo per la Storia dell\'Università di Pavia. University of Pavia. Retrieved 7 January 2023. +
  48. +
  49. ^ Fölsing (1997), pp. 30–31. +
  50. +
  51. ^ Stachel et al. (2008), vol. 1 (1987), doc. 5. +
  52. +
  53. ^ Mehra, Jagdish (2001). "Albert Einstein\'s "First Paper"". Golden Age Of Theoretical Physics, The (Boxed Set Of 2 Vols). World Scientific. ISBN 978-981-4492-85-0. Retrieved 5 January 2021. +
  54. +
  55. ^ The Three-body Problem from Pythagoras to Hawking, Mauri Valtonen, Joanna Anosova, Konstantin Kholshevnikov, Aleksandr Mylläri, Victor Orlov, Kiyotaka Tanikawa, (Springer 2016), p. 43, Simon and Schuster, 2008 +
  56. +
  57. ^ a b Isaacson (2007), p. 16. +
  58. +
  59. ^ Bloom, Howard (2012). The God Problem: How a Godless Cosmos Creates (illustrated ed.). Prometheus Books. p. 294. ISBN 978-1-61614-552-1. Retrieved 8 August 2020. Bloom, Howard (30 August 2012). Extract of page 294. Prometheus Books. ISBN 978-1-61614-552-1. Retrieved 8 August 2020. +
  60. +
  61. ^ a b c Isaacson (2007), p. 17. +
  62. +
  63. ^ Calaprice & Lipscombe (2005), p. 8. +
  64. +
  65. ^ Stachel et al. (2008), vol. 1 (1987), p. 11. +
  66. +
  67. ^ Fölsing (1997), pp. 36–37. +
  68. +
  69. ^ Hunziker, Herbert (2015). "Albert Einstein\'s Magic Mountain: An Aarau Education*". Physics in Perspective. 17 (1): 55–69. Bibcode:2015PhP....17...55H. doi:10.1007/s00016-014-0153-5. ISSN 1422-6944. ref for: Old Cantonal School Aarau +
  70. +
  71. ^ a b Highfield & Carter (1993), pp. 21, 31, 56–57. +
  72. +
  73. ^ Fölsing (1997), p. 40. +
  74. +
  75. ^ Stachel et al. (2008), vol. 1 (1987), docs. 21–27. +
  76. +
  77. ^ a b c Gagnon, Pauline (19 December 2016). "The Forgotten Life of Einstein\'s First Wife". Scientific American Blog Network. Archived from the original on 17 October 2020. Retrieved 17 October 2020. +
  78. +
  79. ^ Troemel-Ploetz, D. (1990). "Mileva Einstein-Marić: The Woman Who Did Einstein\'s Mathematics". Women\'s Studies International Forum. 13 (5): 415–432. doi:10.1016/0277-5395(90)90094-e. +
  80. +
  81. ^ Walker, Evan Harris (February 1989). "Did Einstein Espouse his Spouse\'s Ideas?" (PDF). Physics Today. 42 (2): 9–13. Bibcode:1989PhT....42b...9W. doi:10.1063/1.2810898. Archived from the original (PDF) on 19 January 2012. Retrieved 19 October 2014. +
  82. +
  83. ^ Pais (1994), pp. 1–29. +
  84. +
  85. ^ Holton, G., Einstein, History, and Other Passions, Harvard University Press, 1996, pp. 177–193. +
  86. +
  87. ^ Stachel (2002), pp. 49–56. +
  88. +
  89. ^ Martinez, A. A., "Handling evidence in history: the case of Einstein\'s wife", School Science Review, 86 (316), March 2005, pp. 49–56. "PDF" (PDF). Archived from the original (PDF) on 11 August 2011. Retrieved 11 August 2011. +
  90. +
  91. ^ Renn, Jürgen; Schulmann, Robert, eds. (16 November 2000). Albert Einstein, Mileva Maric: The Love Letters. Translated by Smith, Shawn. Princeton University Press. pp. 73–74, 78. ISBN 978-0-691-08886-0. +
  92. +
  93. ^ Calaprice & Lipscombe (2005), pp. 22–23. +
  94. +
  95. ^ Wüthrich, Urs (11 April 2015). "Die Liebesbriefe des untreuen Einstein" [The love letters of the unfaithful Einstein]. BZ Berner Zeitung (in German). Bern, Switzerland. Archived from the original on 16 April 2015. Retrieved 11 April 2015. Ich denke in innigster Liebe an Dich in jeder freien Minute und bin so unglücklich, wie nur ein Mensch es sein kann. +
  96. +
  97. ^ Calaprice & Lipscombe (2005), p. 50. +
  98. +
  99. ^ a b c d e Hoffmann, Dieter (2013). Einstein\'s Berlin: In the footsteps of a genius. Baltimore: The Johns Hopkins University Press. pp. 2–9, 28. ISBN 978-1-4214-1040-1. +
  100. +
  101. ^ Stachel (1966). +
  102. +
  103. ^ Smith, Dinitia (6 November 1996). "Dark Side of Einstein Emerges in His Letters". The New York Times. Archived from the original on 5 January 2021. Retrieved 17 August 2020. +
  104. +
  105. ^ Stachel (2002), p. 50. +
  106. +
  107. ^ "Volume 9: The Berlin Years: Correspondence, January 1919 – April 1920 (English translation supplement) page 6". einsteinpapers.press.princeton.edu. Archived from the original on 4 October 2021. Retrieved 4 October 2021. +
  108. +
  109. ^ Isaacson (2007), "Main characters", front matter. +
  110. +
  111. ^ Calaprice, Kennefick & Schulmann (2015), p. 62. +
  112. +
  113. ^ Highfield, Roger (10 July 2006). "Einstein\'s theory of fidelity". The Daily Telegraph. Archived from the original on 10 January 2022. +
  114. +
  115. ^ Overbye, Dennis (17 April 2017). "\'Genius\' Unravels the Mysteries of Einstein\'s Universe". The New York Times. Archived from the original on 18 April 2017. +
  116. +
  117. ^ "Genius Albert Einstein\'s Theory of Infidelity". NatGeo TV. Archived from the original on 23 September 2020. Retrieved 9 August 2020. +
  118. +
  119. ^ "Getting up close and personal with Einstein". The Jerusalem Post | JPost.com. Archived from the original on 23 September 2020. Retrieved 29 August 2020. +
  120. +
  121. ^ Highfield & Carter (1993), p. 216. +
  122. +
  123. ^ "Einstein secret love affairs out!". Hindustan Times. 13 July 2006. Archived from the original on 23 September 2020. Retrieved 17 August 2020. +
  124. +
  125. ^ Graydon, Samuel (14 November 2023). Einstein in Time and Space: A Life in 99 Particles (1 ed.). New York: Simon and Schuster. p. 199. ISBN 978-1-9821-8512-1. +
  126. +
  127. ^ "New letters shed light on Einstein\'s love life". NBC News. 11 July 2006. Archived from the original on 22 February 2020. Retrieved 15 August 2020. +
  128. +
  129. ^ "Albert Einstein may have had the IQ, but he needed to work on his EQ". The Economic Times. Archived from the original on 8 February 2021. Retrieved 15 August 2020. +
  130. +
  131. ^ Pogrebin, Robin (1 June 1998). "Love Letters By Einstein at Auction". The New York Times. Archived from the original on 7 November 2020. Retrieved 10 August 2020. +
  132. +
  133. ^ "Einstein\'s letters show affair with spy". The Independent. 2 June 1998. Archived from the original on 16 November 2020. Retrieved 10 November 2020. +
  134. +
  135. ^ Robinson, Andrew (2015). Einstein: A Hundred Years of Relativity. Princeton University Press. pp. 143–145. ISBN 978-0-691-16989-7. Retrieved 19 July 2016. +
  136. +
  137. ^ Neffe (2007), p. 203. +
  138. +
  139. ^ Stachel et al. (2008), vol. 1 (1987), doc. 67. +
  140. +
  141. ^ Fölsing (1997), p. 82. +
  142. +
  143. ^ J. J. O\'Connor; E. F. Robertson (May 2010). "Grossmann biography". MacTutor. School of Mathematics and Statistics, University of St Andrews, Scotland. Archived from the original on 10 September 2015. Retrieved 27 March 2015. +
  144. +
  145. ^ Isaacson (2007), p. 63. +
  146. +
  147. ^ "Einstein at the patent office" (official website). Berne, Switzerland: Swiss Federal Institute of Intellectual Property, IGE/IPI. 6 February 2014. Archived from the original on 30 August 2016. Retrieved 9 September 2016. +
  148. +
  149. ^ a b "FAQ about Einstein and the Institute" (official website). Berne, Switzerland: Swiss Federal Institute of Intellectual Property, IGE/IPI. 27 May 2014. Archived from the original on 12 June 2021. Retrieved 27 March 2015. +
  150. +
  151. ^ Galison (2000), p. 370. +
  152. +
  153. ^ Highfield & Carter (1993), pp. 96–98. +
  154. +
  155. ^ Isaacson (2007), pp. 79–84. +
  156. +
  157. ^ a b Einstein (1901). +
  158. +
  159. ^ Murrell, J. N.; Grobert, N. (January 2002). "The centenary of Einstein\'s first scientific paper". Notes and Records of the Royal Society of London. 56 (1): 89–94. doi:10.1098/rsnr.2002.0169. JSTOR 532124. +
  160. +
  161. ^ a b Einstein (1905b), "Meinem Freunde Herr Dr. Marcel Grossmann gewidmet (Dedicated to my friend, Dr. Marcel Grossmann)". +
  162. +
  163. ^ Einstein (1926b), chap. "A New Determination of Molecular Dimensions". +
  164. +
  165. ^ Mehra, Jagdish (28 February 2001). Golden Age Of Theoretical Physics, The (Boxed Set Of 2 Vols). World Scientific. ISBN 978-981-4492-85-0. +
  166. +
  167. ^ May, Andrew (2017). Clegg, Brian (ed.). Albert Einstein, in 30-Second Physics: The 50 most fundamental concepts in physics, each explained in half a minute. London: Ivy Press. pp. 108–109. ISBN 978-1-78240-514-6. +
  168. +
  169. ^ "Associate Professor at the University of Zurich und professor in Prague (1909–1912)" (digital library). Einstein Online (in German and English). Bern, Switzerland: ETH-Bibliothek Zurich, ETH Zurich, www.ethz.ch. 2014. Archived from the original on 21 August 2014. Retrieved 17 August 2014. +
  170. +
  171. ^ Isaacson (2007), p. 164. +
  172. +
  173. ^ von Hirschhausen, Ulrike (2007). "Von imperialer Inklusion zur nationalen Exklusion:Staatsbürgerschaft in Österreich- Ungarn 1867–1923" (PDF) (WZB Discussion Paper). ZKD – Veröffentlichungsreihe der Forschungsgruppe, "Zivilgesellschaft, Citizenship und politische Mobilisierung in Europa" Schwerpunkt Zivilgesellschaft, Konflikte und Demokratie, Wissenschaftszentrum Berlin für Sozialforschung. Berlin, Germany: WZB Social Science Research Center Berlin. p. 8. ISSN 1860-4315. Archived (PDF) from the original on 9 September 2015. Retrieved 4 August 2015. Eine weitere Diskontinuität bestand viertens darin, dass die Bestimmungen der österreichischen Staatsbürgerschaft, die in den ersten Dritteln des Jahrhunderts auch auf Ungarn angewandt worden waren, seit 1867 nur noch für die cisleithanische Reichshälfte galten. Ungarn entwickelte hingegen jetzt eine eige-ne Staatsbürgerschaft. +
  174. +
  175. ^ Lyth, David (31 January 2019). The Road to Einstein\'s Relativity: Following in the Footsteps of the Giants. CRC Press. ISBN 978-0-429-68268-1. +
  176. +
  177. ^ "Professor at the ETH Zurich (1912–1914)" (digital library). Einstein Online (in German and English). Zurich, Switzerland: ETH-Bibliothek Zurich, ETH Zürich, www.ethz.ch. 2014. Archived from the original on 21 August 2014. Retrieved 17 August 2014. +
  178. +
  179. ^ a b Stachel (2002), p. 534. +
  180. +
  181. ^ a b "Albert Einstein: His Influence on Physics, Philosophy and Politics JL Heilbron – 1982, Published by: American Association for the Advancement of Science via JSTOR". JSTOR 1687520. Archived from the original on 22 November 2021. Retrieved 22 November 2021. +
  182. +
  183. ^ Scheideler (2002), p. 333. +
  184. +
  185. ^ Weinstein (2015), pp. 18–19. +
  186. +
  187. ^ Calaprice & Lipscombe (2005), "Timeline", p. xix. +
  188. +
  189. ^ "Director in the attic". Max-Planck-Gesellschaft, München. Archived from the original on 31 January 2017. Retrieved 9 July 2017. +
  190. +
  191. ^ "Albert Einstein (1879–1955)". Royal Netherlands Academy of Arts and Sciences. Archived from the original on 23 September 2015. Retrieved 21 July 2015. +
  192. +
  193. ^ "Albert Einstein". American Academy of Arts & Sciences. 9 February 2023. Retrieved 13 July 2023. +
  194. +
  195. ^ "APS Member History". search.amphilsoc.org. Retrieved 13 July 2023. +
  196. +
  197. ^ "A New Physics, Based on Einstein". The New York Times. 25 November 1919. p. 17. Archived from the original on 8 June 2019. Retrieved 8 June 2019. +
  198. +
  199. ^ Weinberg, Steven (1972). Gravitation and Cosmology: Principles and applications of the general theory of relativity. John Wiley & Sons, Inc. pp. 19–20. ISBN 9788126517558. +
  200. +
  201. ^ Andrzej, Stasiak (2003). "Myths in science". EMBO Reports. 4 (3): 236. doi:10.1038/sj.embor.embor779. PMC 1315907. +
  202. +
  203. ^ Francis, Matthew (3 March 2017). "How Albert Einstein Used His Fame to Denounce American Racism". Smithsonian Magazine. +
  204. +
  205. ^ Falk, Dan, One Hundred Years Ago, Einstein Was Given a Hero\'s Welcome by America\'s Jews Archived 3 April 2021 at the Wayback Machine, Smithsonian, 2 April 2021 +
  206. +
  207. ^ Hoffmann (1972), pp. 145–148. +
  208. +
  209. ^ Fölsing (1997), pp. 499–508. +
  210. +
  211. ^ "As Einstein Sees American". Archived from the original on 25 February 2020. Retrieved 25 May 2014., Einstein\'s World, a 1931 reprint with minor changes, of his 1921 essay. +
  212. +
  213. ^ Holton (1984), p. 20. +
  214. +
  215. ^ Isaacson (2007), pp. 307–308. +
  216. +
  217. ^ Flood, Alison (12 June 2018). "Einstein\'s travel diaries reveal \'shocking\' xenophobia". The Guardian. Archived from the original on 17 January 2019. Retrieved 13 June 2018. +
  218. +
  219. ^ Katz, Brigit. "Einstein\'s Travel Diaries Reveal His Deeply Troubling Views on Race". Smithsonian Magazine. Archived from the original on 25 December 2020. Retrieved 3 January 2021. +
  220. +
  221. ^ Isaacson (2007), p. 308. +
  222. +
  223. ^ "The Nobel Prize in Physics 1921: Albert Einstein. Banquet Speech by R. Nadolny (in German)". Archived from the original on 12 June 2017. Retrieved 13 June 2017. Retrieved 9 December 2015 via Nobelprize.org +
  224. +
  225. ^ Montes-Santiago, J. (16 July 2017). "[The meeting of Einstein with Cajal (Madrid, 1923): a lost tide of fortune]". Revista de Neurología. 43 (2): 113–117. ISSN 0210-0010. PMID 16838259. +
  226. +
  227. ^ Grandjean, Martin (2018). Les réseaux de la coopération intellectuelle. La Société des Nations comme actrice des échanges scientifiques et culturels dans l\'entre-deux-guerres [The Networks of Intellectual Cooperation. The League of Nations as an Actor of the Scientific and Cultural Exchanges in the Inter-War Period] (in French). Lausanne: Université de Lausanne. Archived from the original on 12 September 2018. Retrieved 18 September 2018. pp. 296–302 +
  228. +
  229. ^ Grandjean, Martin (2017). "Analisi e visualizzazioni delle reti in storia. L\'esempio della cooperazione intellettuale della Società delle Nazioni". Memoria e Ricerca (2): 371–393. doi:10.14647/87204. See also: Martin Grandjean (2017). "French version". Memoria e Ricerca (2): 371–393. doi:10.14647/87204. Archived from the original on 7 November 2017. Retrieved 1 December 2017. (PDF) and "English summary". Archived from the original on 2 November 2017. Retrieved 1 December 2017.. +
  230. +
  231. ^ Shine, Cormac (2018). "Papal Diplomacy by Proxy? Catholic Internationalism at the League of Nations\' International Committee on Intellectual Cooperation". The Journal of Ecclesiastical History. 69 (4): 785–805. doi:10.1017/S0022046917002731. +
  232. +
  233. ^ "The Committee on Intellectual Cooperation of the League of Nations". Science. 64 (1649). American Association for the Advancement of Science: 132–133. 6 August 1926. doi:10.1126/science.64.1649.132.b. JSTOR 1651869. S2CID 239778182. Retrieved 30 May 2022. +
  234. +
  235. ^ Tolmasquim, Alfredo Tiomno (2012). "Science and Ideology in Einstein\'s Visit to South America in 1925". In Lehner, Christoph; Renn, Jürgen; Schemmel, Matthias (eds.). Einstein and the Changing Worldviews of Physics. pp. 117–133. doi:10.1007/978-0-8176-4940-1_6. ISBN 978-0-8176-4939-5. +
  236. +
  237. ^ Gangui, Alejandro; Ortiz, Eduardo L. (2008). "Einstein\'s Unpublished Opening Lecture for His Course on Relativity Theory in Argentina, 1925". Science in Context. 21 (3): 435–450. arXiv:0903.2064. doi:10.1017/S0269889708001853. S2CID 54920641. +
  238. +
  239. ^ Gangui, Alejandro; Ortiz, Eduardo L. (2016). "The scientific impact of Einstein\'s visit to Argentina, in 1925". arXiv:1603.03792 [physics.hist-ph]. +
  240. +
  241. ^ Isaacson (2007), p. 368. +
  242. +
  243. ^ a b c Isaacson (2007), p. 370. +
  244. +
  245. ^ Isaacson (2007), p. 373. +
  246. +
  247. ^ a b Isaacson (2007), p. 374. +
  248. +
  249. ^ Chaplin (1964), p. 320. +
  250. +
  251. ^ Chaplin (1964), p. 322. +
  252. +
  253. ^ Fölsing (1997), p. 659. +
  254. +
  255. ^ Isaacson (2007), p. 404. +
  256. +
  257. ^ "Albert Einstein Quits Germany, Renounces Citizenship". History Unfolded: US Newspapers and the Holocaust. Archived from the original on 17 April 2021. Retrieved 14 March 2021. +
  258. +
  259. ^ a b c d e Isaacson (2007), pp. 407–410. +
  260. +
  261. ^ Richard Kroehling (July 1991). "Albert Einstein: How I See the World". American Masters. PBS. Archived from the original on 14 November 2011. Retrieved 29 May 2018. +
  262. +
  263. ^ Holton (1984). +
  264. +
  265. ^ a b Fred Jerome; Rodger Taylor (2006). Einstein on Race and Racism. Rutgers University Press. p. 10. ISBN 978-0-8135-3952-2. Retrieved 18 June 2015. +
  266. +
  267. ^ Einstein (1954), p. 197. +
  268. +
  269. ^ a b Keyte, Suzanne (9 October 2013). "3 October 1933 – Albert Einstein presents his final speech given in Europe, at the Royal Albert Hall". Royal Albert Hall. Retrieved 20 June 2022. +
  270. +
  271. ^ Robinson, Andrew (2019). Einstein on the Run. Yale University Press. ISBN 978-0-300-23476-3. +
  272. +
  273. ^ Isaacson (2007), p. 422. +
  274. +
  275. ^ "Professor Einstein with Commander Locker-Lampson". Archived from the original on 6 September 2017. Retrieved 2 June 2017., ScienceMuseum.org, UK +
  276. +
  277. ^ Isaacson (2007), pp. 419–420. +
  278. +
  279. ^ a b Gilbert, Martin. Churchill and the Jews, Henry Holt and Company, N.Y. (2007) pp. 101, 176 +
  280. +
  281. ^ Reisman, Arnold (20 November 2006). "What a Freshly Discovered Einstein Letter Says About Turkey Today". History News Network, George Mason University. Archived from the original on 17 April 2014. Retrieved 2 June 2014. +
  282. +
  283. ^ a b c d e Clark (1971). +
  284. +
  285. ^ "Denunciation of German Policy is a Stirring Event", Associated Press, 27 July 1933 +
  286. +
  287. ^ "Stateless Jews: The Exiles from Germany, Nationality Plan", The Guardian (UK) 27 July 1933 +
  288. +
  289. ^ Fölsing (1997), pp. 649, 678. +
  290. +
  291. ^ a b Arntzenius, Linda G. (2011). Institute for Advanced Study. Arcadia Publishing. p. 19. ISBN 978-0-7385-7409-7. Retrieved 18 June 2015. +
  292. +
  293. ^ "Oxford Jewish Personalities". Oxford Chabad Society. Archived from the original on 12 January 2016. Retrieved 7 March 2015. +
  294. +
  295. ^ "How Einstein fled from the Nazis to an Oxford college". The Oxford Times. 2012. Archived from the original on 2 April 2015. Retrieved 7 March 2015. +
  296. +
  297. ^ Fölsing (1997), pp. 686–687. +
  298. +
  299. ^ "In Brief". Institute for Advanced Study. 10 September 2009. Archived from the original on 29 March 2010. Retrieved 4 March 2010. +
  300. +
  301. ^ Weyl, Hermann (2013). Pesic, Peter (ed.). Levels of Infinity: Selected Writings on Mathematics and Philosophy. Dover Publications. p. 5. ISBN 9780486266930. Retrieved 30 May 2022. By 1933, Weyl... left for the newly-founded Institute for Advanced Studies at Princeton, where his colleagues included Einstein, Kurt Gödel, and John von Neumann. +
  302. +
  303. ^ Isaacson (2007), p. 630. +
  304. +
  305. ^ Gosling, F. G. (2010). "The Manhattan Project: Making the Atomic Bomb". U.S. Department of Energy, History Division. p. vii. Archived from the original on 13 June 2015. Retrieved 7 June 2015. +
  306. +
  307. ^ Lanouette, William; Silard, Bela (1992). Genius in the Shadows: A Biography of Leo Szilárd: The Man Behind The Bomb. New York: Charles Scribner\'s Sons. pp. 198–200. ISBN 978-0-684-19011-2. +
  308. +
  309. ^ Diehl, Sarah J.; Moltz, James Clay (2008). Nuclear Weapons and Nonproliferation: A Reference Handbook. ABC-CLIO. p. 218. ISBN 978-1-59884-071-1. Retrieved 7 June 2015. +
  310. +
  311. ^ Hewlett, Richard G.; Anderson, Oscar E. (1962). The New World, 1939–1946 (PDF). University Park: Pennsylvania State University Press. pp. 15–16. ISBN 978-0-520-07186-5. OCLC 637004643. Archived (PDF) from the original on 26 September 2019. Retrieved 7 June 2015. +
  312. +
  313. ^ Einstein, Albert (1952). "On My Participation in the Atom Bomb Project". Archived from the original on 28 August 2015. Retrieved 7 June 2015 – via atomicarchive.org. +
  314. +
  315. ^ Clark (1971), p. 752. +
  316. +
  317. ^ Einstein, Albert; Russell, Bertrand (9 July 1955). The Russell-Einstein Manifesto. London. Archived from the original on 1 March 2020. Retrieved 9 June 2021.{{cite book}}: CS1 maint: location missing publisher (link) +
  318. +
  319. ^ Boyko, Hugo. Science and the Future of Mankind (PDF). Indiana University Press. p. 377. +
  320. +
  321. ^ Isaacson (2007), p. 432. +
  322. +
  323. ^ a b Francis, Matthew (3 March 2017). "How Albert Einstein Used His Fame to Denounce American Racism". Smithsonian Magazine. Archived from the original on 11 February 2021. Retrieved 10 February 2021. +
  324. +
  325. ^ Calaprice (2005), pp. 148–149. +
  326. +
  327. ^ Robeson (2002), p. 565. +
  328. +
  329. ^ a b "Albert Einstein, Civil Rights activist". 12 April 2007. Archived from the original on 2 March 2018. Retrieved 8 June 2014., Harvard Gazette, 12 April 2007 +
  330. +
  331. ^ Jerome, Fred (December 2004). "Einstein, Race, and the Myth of the Cultural Icon". Isis. 95 (4): 627–639. Bibcode:2004Isis...95..627J. doi:10.1086/430653. JSTOR 10.1086/430653. PMID 16011298. S2CID 24738716. +
  332. +
  333. ^ Tobies, Renate (2012). Iris Runge - A Life at the Crossroads of Mathematics, Science, and Industry. Basel: Birkhèauser. p. 116. ISBN 978-3034802512. +
  334. +
  335. ^ Gimbel, Steven (2015). Einstein - His Space and Times. New Haven: Yale University Press. p. 111. ISBN 978-0300196719. +
  336. +
  337. ^ Einstein (1949). +
  338. +
  339. ^ Rowe, David E.; Schulmann, Robert (8 June 2007a). David A., Walsh (ed.). "What Were Einstein\'s Politics?". History News Network. Archived from the original on 3 February 2019. Retrieved 29 July 2012. +
  340. +
  341. ^ Rowe & Schulmann (2013), pp. 412, 413. +
  342. +
  343. ^ Isaacson (2007), pp. 487, 494, 550. +
  344. +
  345. ^ Bulletin of the Atomic Scientists 4 (February 1948), No. 2 35–37: \'A Reply to the Soviet Scientists, December 1947\' +
  346. +
  347. ^ Waldrop, Mitch (19 April 2017). "Why the FBI Kept a 1,400-Page File on Einstein". National Geographic. Archived from the original on 26 May 2017. Retrieved 7 June 2017. +
  348. +
  349. ^ "Einstein on Gandhi (Einstein\'s letter to Gandhi – Courtesy:Saraswati Albano-Müller & Notes by Einstein on Gandhi – Source: The Hebrew University of Jerusalem)". Gandhiserve.org. 18 October 1931. Archived from the original on 17 January 2012. Retrieved 24 January 2012. +
  350. +
  351. ^ "Einstein\'s letter and Gandhi\'s answer". Archived from the original on 9 June 2014. Retrieved 22 August 2021., gandhiserve.org +
  352. +
  353. ^ Dennis Overbye (25 January 2005). "Brace Yourself! Here Comes Einstein\'s Year". The New York Times. Archived from the original on 30 October 2020. Retrieved 27 October 2020. Hebrew University ... which he helped found +
  354. +
  355. ^ Isaacson (2007), p. 290. +
  356. +
  357. ^ Rowe & Schulmann (2007), p. 161. +
  358. +
  359. ^ Rowe & Schulmann (2007), p. 158. +
  360. +
  361. ^ Einstein, Albert (10 November 2013). Rowe, David E.; Schulmann, Robert (eds.). Einstein on Politics. Princeton University Press. p. 152. ISBN 978-0691160207. I consider raising Jewish self-esteem essential, also in the interest of a natural coexistence with non-Jews. This was my major motive for joining the Zionist movement. +
  362. +
  363. ^ a b c Jerome, Fred (2009). Einstein on Israel and Zionism (1 ed.). New York: St. Martin\'s Press. pp. 156, 176, 182. ISBN 978-0-312-36228-7. +
  364. +
  365. ^ "ISRAEL: Einstein Declines". Time. 1 December 1952. Archived from the original on 18 May 2008. Retrieved 31 March 2010. +
  366. +
  367. ^ Rosenkranz, Ze\'ev (6 November 2002). The Einstein Scrapbook. Baltimore, Maryland: Johns Hopkins University Press. p. 103. ISBN 978-0-8018-7203-7. +
  368. +
  369. ^ a b Isaacson (2007), p. 522. +
  370. +
  371. ^ Hitchens, Christopher, ed. (2007). "Selected Writings on Religion: Albert Einstein". The Portable Atheist: Essential Readings for the Nonbeliever. Da Capo Press. p. 155. ISBN 978-0-306-81608-6. +
  372. +
  373. ^ Isaacson (2008), p. 325. +
  374. +
  375. ^ a b Calaprice (2000), p. 218. +
  376. +
  377. ^ Isaacson (2008), p. 390. +
  378. +
  379. ^ Calaprice (2010), p. 340. +
  380. +
  381. ^ "Letter to M. Berkowitz, 25 October 1950". Retrieved 16 February 2017. Einstein Archive 59–215. +
  382. +
  383. ^ Isaacson (2008), p. 461. +
  384. +
  385. ^ Dowbiggin, Ian (2003). A Merciful End. New York: Oxford University Press, Dowbiggin, Ian (9 January 2003). p. 41. Oxford University Press. ISBN 978-0-19-803515-2. Retrieved 26 March 2018. +
  386. +
  387. ^ Einstein (1995), p. 62. +
  388. +
  389. ^ Dvorsky, George (23 October 2012). "Einstein\'s \'I don\'t believe in God\' letter has sold on eBay..." io9. Archived from the original on 9 December 2015. Retrieved 23 April 2019. +
  390. +
  391. ^ "Albert Einstein (1879–1955)". International Vegetarian Union. +
  392. +
  393. ^ "Was Albert Einstein vegan?". AreTheyVegan.com. 27 March 2020. +
  394. +
  395. ^ Duchen, Jessica (28 January 2011). "The relative beauty of the violin". The Independent. Archived from the original on 22 July 2020. Retrieved 23 August 2017. +
  396. +
  397. ^ "Einstein and his love of music" (PDF). Physics World. January 2005. Archived from the original (PDF) on 28 August 2015. +
  398. +
  399. ^ a b c d Peter Galison; Gerald James Holton; Silvan S. Schweber (2008). Einstein for the 21st Century: His Legacy in Science, Art, and Modern Culture. Princeton University Press. pp. 161–164. ISBN 978-0-691-13520-5. +
  400. +
  401. ^ Article "Alfred Einstein", in The New Grove Dictionary of Music and Musicians, ed. Stanley Sadie. 20 vol. London, Macmillan Publishers Ltd., 1980. ISBN 978-1-56159-174-9 +
  402. +
  403. ^ The Concise Edition of Baker\'s Biographical Dictionary of Musicians, 8th ed. Revised by Nicolas Slonimsky. New York, Schirmer Books, 1993. ISBN 978-0-02-872416-4 +
  404. +
  405. ^ Cariaga, Daniel, "Not Taking It with You: A Tale of Two Estates", Los Angeles Times Archived 21 January 2019 at the Wayback Machine, 22 December 1985. Retrieved April 2012. +
  406. +
  407. ^ "Relaxed Einstein signs for a fellow violinist before sailing to Germany for the last time". RR Auction. 2010. Archived from the original on 24 May 2013. Retrieved 6 June 2012. +
  408. +
  409. ^ "The Case of the Scientist with a Pulsating Mass". Medscape. 14 June 2002. Archived from the original on 8 July 2009. Retrieved 11 June 2007. +
  410. +
  411. ^ Albert Einstein Archives (April 1955). "Draft of projected Telecast Israel Independence Day, April 1955 (last statement ever written)". Einstein Archives Online. Archived from the original on 13 March 2007. Retrieved 14 March 2007. +
  412. +
  413. ^ Cohen, J. R.; Graver, L. M. (November 1995). "The ruptured abdominal aortic aneurysm of Albert Einstein". Surgery, Gynecology & Obstetrics. 170 (5): 455–458. PMID 2183375. +
  414. +
  415. ^ Cosgrove, Ben (14 March 2014). "The Day Albert Einstein Died: A Photographer\'s Story". Time. Archived from the original on 12 November 2014. Retrieved 24 April 2018. +
  416. +
  417. ^ "The Long, Strange Journey of Einstein\'s Brain". NPR. Archived from the original on 14 July 2019. Retrieved 3 October 2007. +
  418. +
  419. ^ Cosgrove, Benjamin; Morse, Ralph (14 March 2014). "The Day Albert Einstein Died: A Photographer\'s Story". Life. Archived from the original on 19 March 2021. Retrieved 10 March 2021. +
  420. +
  421. ^ O\'Connor, J. J.; Robertson, E.F. (1997). "Albert Einstein". The MacTutor History of Mathematics archive. School of Mathematics and Statistics, University of St. Andrews. Archived from the original on 13 February 2007. Retrieved 11 March 2007. +
  422. +
  423. ^ Late City, ed. (18 April 1955). Written at Princeton, NJ. "Dr. Albert Einstein Dies in Sleep at 76; World Mourns Loss of Great Scientist, Rupture of Aorta Causes Death, Body Cremated, Memorial Here Set". The New York Times. Vol. CIV, no. 35, 514. New York (published 19 April 1955). p. 1. ISSN 0362-4331. Archived from the original on 25 May 2014. Retrieved 24 May 2014. +
  424. +
  425. ^ Oppenheimer, J. Robert (March 1979). "Oppenheimer on Einstein". Bulletin of the Atomic Scientists. 35 (3): 38. Bibcode:1979BuAtS..35c..36O. doi:10.1080/00963402.1979.11458597. Retrieved 12 January 2017. +
  426. +
  427. ^ Unna, Issachar (22 June 2007). "An Ongoing Power of Attraction". Haaretz. Archived from the original on 16 June 2021. Retrieved 15 June 2021. +
  428. +
  429. ^ a b Paul Arthur Schilpp, ed. (1951). Albert Einstein: Philosopher-Scientist. Vol. II. New York: Harper and Brothers Publishers (Harper Torchbook edition). pp. 730–746.. His non-scientific works include: About Zionism: Speeches and Lectures by Professor Albert Einstein (1930), "Why War?" (1933, co-authored by Sigmund Freud), The World As I See It (1934), Out of My Later Years (1950), and a book on science for the general reader, The Evolution of Physics (1938, co-authored by Leopold Infeld). +
  430. +
  431. ^ Stachel et al. (2008). +
  432. +
  433. ^ Overbye, Dennis (4 December 2014). "Thousands of Einstein Documents Are Now a Click Away". The New York Times. Archived from the original on 1 January 2022. Retrieved 4 January 2015. +
  434. +
  435. ^ a b ""Einstein archive at the Instituut-Lorentz". Archived from the original on 19 May 2015. Retrieved 21 August 2005.". Instituut-Lorentz. 2005. Retrieved 21 November 2005. +
  436. +
  437. ^ Pietrow, Alexander G.M. (2019). "Investigations into the origin of Einstein\'s Sink". Studium. 11 (4): 260–268. arXiv:1905.09022. Bibcode:2019Studi..11E...1P. doi:10.18352/studium.10183 (inactive 31 January 2024). S2CID 162168640.{{cite journal}}: CS1 maint: DOI inactive as of January 2024 (link) +
  438. +
  439. ^ a b c Einstein (1905a). +
  440. +
  441. ^ Das, Ashok (2003). Lectures on quantum mechanics. Hindustan Book Agency. p. 59. ISBN 978-81-85931-41-8. +
  442. +
  443. ^ Spielberg, Nathan; Anderson, Bryon D. (1995). Seven ideas that shook the universe (2nd ed.). John Wiley & Sons. p. 263. ISBN 978-0-471-30606-1. +
  444. +
  445. ^ Einstein (1905c). +
  446. +
  447. ^ a b Einstein (1905d). +
  448. +
  449. ^ Major, Fouad G. (2007). The quantum beat: principles and applications of atomic clocks (2nd ed.). Springer. p. 142. ISBN 978-0-387-69533-4. Retrieved 18 June 2015. +
  450. +
  451. ^ Lindsay, Robert Bruce; Margenau, Henry (1981). Foundations of physics. Ox Bow Press. p. 330. ISBN 978-0-918024-17-6. Retrieved 18 June 2015. +
  452. +
  453. ^ Einstein (1905e). +
  454. +
  455. ^ a b Kuepper, Hans-Josef. "List of Scientific Publications of Albert Einstein". Einstein-website.de. Archived from the original on 8 May 2013. Retrieved 3 April 2011. +
  456. +
  457. ^ Levenson, Thomas. "Genius Among Geniuses". Einstein\'s Big Idea. Boston: WBGH. Archived from the original on 6 November 2018. Retrieved 20 June 2015 – via NOVA by Public Broadcasting Service (PBS). +
  458. +
  459. ^ Fölsing (1997), pp. 178–198. +
  460. +
  461. ^ Stachel (2002), pp. vi, 15, 90, 131, 215. +
  462. +
  463. ^ Pais (1982), pp. 382–386. +
  464. +
  465. ^ Pais (1982), pp. 151–152. +
  466. +
  467. ^ Fraknoi, Andrew; et al. (2022). Astronomy 2e (2e ed.). OpenStax. pp. 800–815. ISBN 978-1-951693-50-3. OCLC 1322188620. +
  468. +
  469. ^ Einstein (1923). +
  470. +
  471. ^ Pais (1982), pp. 179–183. +
  472. +
  473. ^ Stachel et al. (2008), pp. 273–274, vol. 2: The Swiss Years: Writings, 1900–1909. +
  474. +
  475. ^ Pais (1982), pp. 194–195. +
  476. +
  477. ^ Einstein (1916). +
  478. +
  479. ^ Einstein (1918). +
  480. +
  481. ^ a b c Nadia Drake (11 February 2016). "Found! Gravitational Waves, or a Wrinkle in Spacetime". National Geographic. Archived from the original on 12 February 2016. Retrieved 6 July 2016. +
  482. +
  483. ^ "Gravity investigated with a binary pulsar-Press Release: The 1993 Nobel Prize in Physics". Nobel Foundation. Archived from the original on 10 August 2018. Retrieved 6 July 2016. +
  484. +
  485. ^ Abbott, Benjamin P.; et al. (LIGO Scientific Collaboration and Virgo Collaboration) (2016). "Observation of Gravitational Waves from a Binary Black Hole Merger" (PDF). Phys. Rev. Lett. 116 (6): 061102. arXiv:1602.03837. Bibcode:2016PhRvL.116f1102A. doi:10.1103/PhysRevLett.116.061102. PMID 26918975. S2CID 124959784. Archived (PDF) from the original on 16 February 2016. Retrieved 6 July 2016. +
  486. +
  487. ^ "Gravitational Waves: Ripples in the fabric of space-time". LIGO | MIT. 11 February 2016. Archived from the original on 19 February 2016. Retrieved 12 February 2016. +
  488. +
  489. ^ "Scientists make first direct detection of gravitational waves". Jennifer Chu. MIT News. 11 February 2016. Archived from the original on 7 April 2019. Retrieved 12 February 2016. +
  490. +
  491. ^ Ghosh, Pallab (11 February 2016). "Einstein\'s gravitational waves \'seen\' from black holes". BBC News. Archived from the original on 11 February 2016. Retrieved 12 February 2016. +
  492. +
  493. ^ Overbye, Dennis (11 February 2016). "Gravitational Waves Detected, Confirming Einstein\'s Theory". The New York Times. ISSN 0362-4331. Archived from the original on 11 February 2016. Retrieved 12 February 2016. +
  494. +
  495. ^ Norton, John (1984). "How Einstein Found His Field Equations: 1912–1915". Historical Studies in the Physical Sciences. 14 (2): 253–316. doi:10.2307/27757535. ISSN 0073-2672. JSTOR 27757535. +
  496. +
  497. ^ van Dongen, Jeroen (2010) Einstein\'s Unification Cambridge University Press, p. 23. +
  498. +
  499. ^ Einstein (1917a). +
  500. +
  501. ^ Pais (1994), pp. 285–286. +
  502. +
  503. ^ North, J.D. (1965). The Measure of the Universe: A History of Modern Cosmology. New York: Dover. pp. 81–83. +
  504. +
  505. ^ a b Einstein (1931). +
  506. +
  507. ^ a b O\'Raifeartaigh, C; McCann, B (2014). "Einstein\'s cosmic model of 1931 revisited: An analysis and translation of a forgotten model of the universe" (PDF). The European Physical Journal H. 39 (2014): 63–85. arXiv:1312.2192. Bibcode:2014EPJH...39...63O. doi:10.1140/epjh/e2013-40038-x. S2CID 53419239. Archived (PDF) from the original on 29 September 2020. Retrieved 31 December 2019. +
  508. +
  509. ^ Einstein & de Sitter (1932). +
  510. +
  511. ^ Nussbaumer, Harry (2014). "Einstein\'s conversion from his static to an expanding universe". Eur. Phys. J. H. 39 (1): 37–62. arXiv:1311.2763. Bibcode:2014EPJH...39...37N. doi:10.1140/epjh/e2013-40037-6. S2CID 122011477. +
  512. +
  513. ^ Nussbaumer and Bieri (2009). Discovering the Expanding Universe. Cambridge: Cambridge University Press. pp. 144–152. +
  514. +
  515. ^ Zimmer, Carl (9 June 2013). "The Genius of Getting It Wrong". The New York Times. Archived from the original on 1 January 2022. +
  516. +
  517. ^ Castelvecchi, Davide (2014). "Einstein\'s lost theory uncovered". Nature News & Comment. 506 (7489): 418–419. Bibcode:2014Natur.506..418C. doi:10.1038/506418a. PMID 24572403. S2CID 205080245. +
  518. +
  519. ^ "On His 135th Birthday, Einstein is Still Full of Surprises". Out There. 14 March 2014. Archived from the original on 18 March 2014. Retrieved 17 March 2014. +
  520. +
  521. ^ a b O\'Raifeartaigh, C.; McCann, B.; Nahm, W.; Mitton, S. (2014). "Einstein\'s steady-state theory: an abandoned model of the cosmos" (PDF). Eur. Phys. J. H. 39 (3): 353–369. arXiv:1402.0132. Bibcode:2014EPJH...39..353O. doi:10.1140/epjh/e2014-50011-x. S2CID 38384067. Archived (PDF) from the original on 29 September 2020. Retrieved 31 December 2019. +
  522. +
  523. ^ a b Nussbaumer, Harry (2014). "Einstein\'s aborted attempt at a dynamic steady-state universe". In memoriam Hilmar Duerbeck. p. 463. arXiv:1402.4099. Bibcode:2014arXiv1402.4099N. ISBN 978-3-944913-56-8. +
  524. +
  525. ^ Hoyle (1948). "A New Model for the Expanding Universe". MNRAS. 108 (5): 372. Bibcode:1948MNRAS.108..372H. doi:10.1093/mnras/108.5.372. +
  526. +
  527. ^ Bondi; Gold (1948). "The Steady-State Theory of the Expanding Universe". MNRAS. 108 (3): 252. Bibcode:1948MNRAS.108..252B. doi:10.1093/mnras/108.3.252. +
  528. +
  529. ^ Amir Aczel (7 March 2014). "Einstein\'s Lost Theory Describes a Universe Without a Big Bang". The Crux. Archived from the original on 19 March 2014. Retrieved 17 March 2014. +
  530. +
  531. ^ Byers, Nina (23 September 1998). "E. Noether\'s Discovery of the Deep Connection Between Symmetries and Conservation Laws". arXiv:physics/9807044. +
  532. +
  533. ^ Goldberg, J. N. (1958). "Conservation laws in general relativity". Physical Review. 111 (1): 315–320. Bibcode:1958PhRv..111..315G. doi:10.1103/PhysRev.111.315. +
  534. +
  535. ^ Einstein & Rosen (1935). +
  536. +
  537. ^ "2015 – General Relativity\'s Centennial". American Physical Society. 2015. Archived from the original on 15 November 2018. Retrieved 7 April 2017. +
  538. +
  539. ^ Lindley, David (25 March 2005). "Focus: The Birth of Wormholes". Physics. 15: 11. doi:10.1103/physrevfocus.15.11. +
  540. +
  541. ^ Wheeler, John Archibald (18 June 2010). Geons, Black Holes, and Quantum Foam: A Life in Physics. W. W. Norton & Company. ISBN 978-0-393-07948-7. +
  542. +
  543. ^ Kersting, Magdalena (May 2019). "Free fall in curved spacetime—how to visualise gravity in general relativity". Physics Education. 54 (3): 035008. Bibcode:2019PhyEd..54c5008K. doi:10.1088/1361-6552/ab08f5. hdl:10852/74677. ISSN 0031-9120. S2CID 127471222. +
  544. +
  545. ^ Tamir, M (2012). "Proving the principle: Taking geodesic dynamics too seriously in Einstein\'s theory" (PDF). Studies in History and Philosophy of Modern Physics. 43 (2): 137–154. Bibcode:2012SHPMP..43..137T. doi:10.1016/j.shpsb.2011.12.002. +
  546. +
  547. ^ Malament, David (2012). "A Remark About the "Geodesic Principle" in General Relativity" (PDF). In Frappier, M.; Brown, D.; DiSalle, R. (eds.). Analysis and Interpretation in the Exact Sciences. The Western Ontario Series in Philosophy of Science. Vol. 78. Springer. pp. 245–252. doi:10.1007/978-94-007-2582-9_14. ISBN 978-94-007-2581-2. Though the geodesic principle can be recovered as theorem in general relativity, it is not a consequence of Einstein\'s equation (or the conservation principle) alone. Other assumptions are needed to derive the theorems in question. +
  548. +
  549. ^ "Celebrating Einstein \'Solid Cold\'. U.S. DOE". Archived from the original on 19 July 2017. Retrieved 21 February 2011., Office of Scientific and Technical Information, 2011. +
  550. +
  551. ^ Einstein (1924). +
  552. +
  553. ^ "Cornell and Wieman Share 2001 Nobel Prize in Physics". 9 October 2001. Archived from the original on 10 June 2007. Retrieved 11 June 2007. +
  554. +
  555. ^ Pais (1982), p. 522. +
  556. +
  557. ^ Stachel et al. (2008), pp. 270ff, vol. 4: The Swiss Years: Writings, 1912–1914. +
  558. +
  559. ^ Einstein (1917b). +
  560. +
  561. ^ Duncan, Anthony; Janssen, Michel (2019). Constructing quantum mechanics. Volume 1, The scaffold : 1900–1923 (1st ed.). Oxford: Oxford University Press. pp. 133–142. ISBN 978-0-19-258422-9. OCLC 1119627546. +
  562. +
  563. ^ Hanle, Paul A. (July 1979). "The Schrödinger-Einstein correspondence and the sources of wave mechanics". American Journal of Physics. 47 (7): 644–648. Bibcode:1979AmJPh..47..644H. doi:10.1119/1.11950. ISSN 0002-9505. +
  564. +
  565. ^ Raman, V. V.; Forman, Paul (1969). "Why Was It Schrödinger Who Developed de Broglie\'s Ideas?". Historical Studies in the Physical Sciences. 1: 291–314. doi:10.2307/27757299. ISSN 0073-2672. JSTOR 27757299. +
  566. +
  567. ^ Andrews, Robert (2003). The New Penguin Dictionary of Modern Quotations. Penguin UK. p. 499. ISBN 978-0-14-196531-4. Retrieved 18 June 2015. +
  568. +
  569. ^ Pais, Abraham (October 1979). "Einstein and the quantum theory" (PDF). Reviews of Modern Physics. 51 (4): 863–914. Bibcode:1979RvMP...51..863P. doi:10.1103/RevModPhys.51.863. Archived (PDF) from the original on 29 August 2019. Retrieved 18 November 2019. +
  570. +
  571. ^ Bohr, N. "Discussions with Einstein on Epistemological Problems in Atomic Physics". The Value of Knowledge: A Miniature Library of Philosophy. Marxists Internet Archive. Archived from the original on 13 September 2010. Retrieved 30 August 2010. From Albert Einstein: Philosopher-Scientist (1949), publ. Cambridge University Press, 1949. Niels Bohr\'s report of conversations with Einstein. +
  572. +
  573. ^ Einstein (1969). +
  574. +
  575. ^ Schlosshauer, Maximilian; Kofler, Johannes; Zeilinger, Anton (1 August 2013). "A snapshot of foundational attitudes toward quantum mechanics". Studies in History and Philosophy of Science Part B: Studies in History and Philosophy of Modern Physics. 44 (3): 222–230. arXiv:1301.1069. Bibcode:2013SHPMP..44..222S. doi:10.1016/j.shpsb.2013.04.004. ISSN 1355-2198. S2CID 55537196. +
  576. +
  577. ^ a b Howard (1990). +
  578. +
  579. ^ a b Harrigan & Spekkens (2010). +
  580. +
  581. ^ Einstein, Podolsky & Rosen (1935). +
  582. +
  583. ^ Peres (2002). +
  584. +
  585. ^ Mermin (1993). +
  586. +
  587. ^ Penrose (2007). +
  588. +
  589. ^ Bell (1966). +
  590. +
  591. ^ Fine (2017). +
  592. +
  593. ^ Einstein (1950). +
  594. +
  595. ^ Goenner, Hubert F. M. (1 December 2004). "On the History of Unified Field Theories". Living Reviews in Relativity. 7 (1): 2. Bibcode:2004LRR.....7....2G. doi:10.12942/lrr-2004-2. ISSN 1433-8351. PMC 5256024. PMID 28179864. +
  596. +
  597. ^ +Richardson, O. W. (1908). "A Mechanical Effect Accompanying Magnetization". Physical Review. Series I. 26 (3): 248–253. Bibcode:1908PhRvI..26..248R. doi:10.1103/PhysRevSeriesI.26.248. +
  598. +
  599. ^ +Einstein, A.; de Haas, W. J. (1915). "Experimenteller Nachweis der Ampereschen Molekularströme" [Experimental Proof of Ampère\'s Molecular Currents]. Deutsche Physikalische Gesellschaft, Verhandlungen (in German). 17: 152–170. +
  600. +
  601. ^ +Einstein, A.; de Haas, W. J. (1915). "Experimental proof of the existence of Ampère\'s molecular currents" (PDF). Koninklijke Akademie van Wetenschappen te Amsterdam, Proceedings. 18: 696–711. Bibcode:1915KNAB...18..696E. +
  602. +
  603. ^ San Miguel, Alfonso; Pallandre, Bernard (13 March 2024). "Revisiting the Einstein-de Haas experiment: the Ampère Museum\'s hidden treasure" (PDF). Europhysics News: 12–14. +
  604. +
  605. ^ Johnston, Hamish (17 March 2024). "Einstein\'s only experiment is found in French museum". Physics World. Retrieved 24 March 2024. +
  606. +
  607. ^ Goettling, Gary. "Einstein\'s refrigerator". Archived from the original on 25 May 2005. Georgia Tech Alumni Magazine. 1998. Retrieved 12 November 2014. Leó Szilárd, a Hungarian physicist who later worked on the Manhattan Project, is credited with the discovery of the chain reaction +
  608. +
  609. ^ Alok, Jha (21 September 2008). "Einstein fridge design can help global cooling". The Guardian. Archived from the original on 24 January 2011. Retrieved 22 February 2011. +
  610. +
  611. ^ "Electrodynamic movement of fluid metals particularly for refrigerating machines". +
  612. +
  613. ^ "Device, in particular for sound reproduction devices, in which changes in electrical current through magnetostriction cause movements of a magnetic body". +
  614. +
  615. ^ Albert Einstein\'s patents. 2006. World Pat Inf. 28/2, 159–65. M. Trainer. doi: 10.1016/j.wpi.2005.10.012 +
  616. +
  617. ^ "Obituary". The New York Times. 12 July 1986. Archived from the original on 10 September 2017. Retrieved 3 April 2011. +
  618. +
  619. ^ "Letters Reveal Einstein Love Life". BBC News. 11 July 2006. Archived from the original on 2 May 2019. Retrieved 14 March 2007. +
  620. +
  621. ^ "United States District Court, Central District of California, Case No. CV10–03790 AHM (JCx)". 15 October 2012. Archived from the original on 21 January 2020. Retrieved 24 November 2019. +
  622. +
  623. ^ "United States District Court, Central District of California, Case No.: CV-10-3790-AB (JCx)". 15 January 2015. Archived from the original on 25 July 2020. Retrieved 24 November 2019. +
  624. +
  625. ^ "Einstein". Corbis Rights Representation. Archived from the original on 19 August 2008. Retrieved 8 August 2008. +
  626. +
  627. ^ "Place name detail: Mount Einstein". New Zealand Gazetteer. New Zealand Geographic Board. Retrieved 21 August 2022. +
  628. +
  629. ^ Halpern, Paul (2019). "Albert Einstein, celebrity scientist". Physics Today. 72 (4): 38–45. doi:10.1063/PT.3.4183. S2CID 187603798. Archived from the original on 14 April 2021. Retrieved 21 February 2021. +
  630. +
  631. ^ Fahy, Declan (2015). "A Brief History Of Scientific Celebrity". Skeptical Inquirer. Vol. 39, no. 4. Archived from the original on 10 May 2021. Retrieved 21 February 2021. +
  632. +
  633. ^ Missner, Marshall (May 1985). "Why Einstein Became Famous in America". Social Studies of Science. 15 (2): 267–291. doi:10.1177/030631285015002003. JSTOR 285389. S2CID 143398600. +
  634. +
  635. ^ Libman, E. (14 January 1939). "Disguise". The New Yorker. Archived from the original on 25 July 2020. Retrieved 15 April 2020. +
  636. +
  637. ^ McTee, Cindy. "Einstein\'s Dream for orchestra". Cindymctee.com. Archived from the original on 18 April 2017. Retrieved 17 July 2010. +
  638. +
  639. ^ Golden, Frederic (3 January 2000). "Person of the Century: Albert Einstein". Time. Archived from the original on 21 February 2006. Retrieved 25 February 2006. +
  640. +
  641. ^ Novak, Matt (16 May 2015). "9 Albert Einstein Quotes That Are Completely Fake". Gizmodo. Archived from the original on 5 July 2018. Retrieved 4 May 2018. +
  642. +
  643. ^ "Did Albert Einstein Humiliate an Atheist Professor?". Snopes. 29 June 2004. Archived from the original on 4 November 2021. Retrieved 4 May 2018. +
  644. +
  645. ^ "Einsteinium – Element". Royal Society of Chemistry. Retrieved 16 December 2022. +
  646. +
  647. ^ "Einstein Papers Project". California Institute of Technology. Retrieved 5 November 2022. +
  648. +
  649. ^ "Albert Einstein". Princeton University Press. Retrieved 5 November 2022. +
  650. +
+

Works cited

+
+ +
+

Further reading

+
+ +
+

External links

+ + + + + + + + + + + +
+
+ +
+
+ +
+ +
+
+
+
    +
  • + +
  • +
+
+ + + +' +]; diff --git a/tests/cache/gist.github.com.oscarotero-7749998.json.php b/tests/cache/gist.github.com.oscarotero-7749998.json.php new file mode 100644 index 00000000..e5f3b285 --- /dev/null +++ b/tests/cache/gist.github.com.oscarotero-7749998.json.php @@ -0,0 +1,64 @@ + [ + 'server' => [ + 'GitHub.com' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:24 GMT' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'vary' => [ + 'X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With' + ], + 'etag' => [ + 'W/"1d9fb08988578bbd09f38d77ed74f169"' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains; preload' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '0' + ], + 'referrer-policy' => [ + 'origin-when-cross-origin, strict-origin-when-cross-origin' + ], + 'content-security-policy' => [ + 'default-src \'none\'; base-uri \'self\'; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src \'self\' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com api.githubcopilot.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com/v1/engines/github-completion/completions *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action \'self\' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors \'none\'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src \'self\' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src \'self\'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src \'unsafe-inline\' github.githubassets.com; upgrade-insecure-requests; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/' + ], + 'content-encoding' => [ + 'gzip' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'content-length' => [ + '2726' + ], + 'x-github-request-id' => [ + 'FF15:51E7:5C7C460:5E3F8CB:666722DC' + ], + 'Content-Location' => [ + 'https://gist.github.com/oscarotero/7749998.json' + ], + 'X-Request-Time' => [ + '0.272 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"description":"","public":true,"created_at":"2013-12-02T14:10:20.000Z","files":["Git-cheatsheet.sh"],"owner":"oscarotero","div":"
\\n
\\n
\\n
\\n
\\n \\n
\\n\\n \\n
\\n\\n \\n\\n\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
# Undo latest commit
git reset --soft HEAD^
\\n
# Undo the changes of a commit (creating a new commit)
git revert <commit>
\\n
# Undo latest merge (before push)
git reset --merge ORIG_HEAD
\\n
# Merge a branch using the version of the current branch in case of conflicts
git merge <branch> -s ours
\\n
# Discard changes for a particular file after commit
git reset HEAD <file>
\\n
# Unstage the current staged changes
git reset
\\n
# Create, fetch a remote branch and switch to it
git checkout --track <remote>/<branch>
\\n
# Remove a file from git but not from disc
git rm --cached <file>
\\n
# Reapply an old commit again
git cherry-pick <commit>
\\n
# Ignore the changes of a file
git update-index --assume-unchanged <file>
\\n
# Not ignore the changes of a file
git update-index --no-assume-unchanged <file>
\\n
# List all "assume-unchanged" files
git ls-files -v|grep '^h'
\\n
# Display who did the latest change in each line (ignoring whitespaces)
git blame <filename> -w
\\n
# Remove all local branches removed in remote
git fetch origin --prune
\\n
# Remove untracked local files
git clean -f
\\n
# Remove untracked local files and folders
git clean -fd
\\n
# Remove remote branch
git push <remote> --delete <branch>
\\n
# Go to an old commit
git read-tree <commit>
\\n
# Use the ~/.gitignore file to ignore globally certain files
git config --global core.excludesfile '~/.gitignore'
\\n
\\n\\n\\n
\\n\\n
\\n
\\n\\n
\\n
\\n view raw\\n \\n Git-cheatsheet.sh\\n \\n hosted with ❤ by GitHub\\n
\\n
\\n
\\n","stylesheet":"https://github.githubassets.com/assets/gist-embed-8c1a5bab9782.css"}' +]; diff --git a/tests/cache/gist.github.com.oscarotero-7749998.php b/tests/cache/gist.github.com.oscarotero-7749998.php new file mode 100644 index 00000000..9ae384bd --- /dev/null +++ b/tests/cache/gist.github.com.oscarotero-7749998.php @@ -0,0 +1,1361 @@ + [ + 'server' => [ + 'GitHub.com' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:24 GMT' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'vary' => [ + 'X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With' + ], + 'etag' => [ + 'W/"a77645b2d26c439dcad637b496321a1b"' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains; preload' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '0' + ], + 'referrer-policy' => [ + 'origin-when-cross-origin, strict-origin-when-cross-origin' + ], + 'content-security-policy' => [ + 'default-src \'none\'; base-uri \'self\'; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src \'self\' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com api.githubcopilot.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com/v1/engines/github-completion/completions *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action \'self\' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors \'none\'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src \'self\' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src \'self\'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src \'unsafe-inline\' github.githubassets.com; upgrade-insecure-requests; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/' + ], + 'content-encoding' => [ + 'gzip' + ], + 'set-cookie' => [ + '_gh_sess=TaBFSTninIr5%2FPMwas1MAVXOvIB160K2v1xE0%2FtcCs7HakDCe0vHhJ91uYspl10tEjUAAK4Jj%2B%2FPG0dOP2O27B3ZggfR6qtOrESpGIqrbsnhMn0fLROv2QJM5MY%2FqgzkAs%2BGjQiNgULxbumd3HMEcA%2FSnUIWIuYPwjTxBZeKfzdhC2uHFBBOPoickKGAc8Kf5MkqCEhE8RwEvQpDVjOwrROEgbhU%2BI2iGkhVEOW9eFD%2FX5gVczqFf45iPJTQQ7qmdW9DZpB57%2F7679lNGJXZOw%3D%3D--LXlSrVfwCDf0AEZX--5hSsqjJbU3X%2FTEnBRXx9Qw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax', + '_octo=GH1.1.1732253754.1718035163; Path=/; Domain=github.com; Expires=Tue, 10 Jun 2025 15:59:23 GMT; Secure; SameSite=Lax', + 'logged_in=no; Path=/; Domain=github.com; Expires=Tue, 10 Jun 2025 15:59:23 GMT; HttpOnly; Secure; SameSite=Lax' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'x-github-request-id' => [ + 'FF14:1FF7FA:4C7223D:4DD7B75:666722DB' + ], + 'Content-Location' => [ + 'https://gist.github.com/oscarotero/7749998' + ], + 'X-Request-Time' => [ + '0.536 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Git-cheatsheet.sh · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ Skip to content + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + +
+
+
+ + +
+
+

+ Instantly share code, notes, and snippets. +

+
+
+ + +
+
+ + +
+
+
+
+ @oscarotero +
+
+ + +
+ Last active + December 3, 2016 11:29 +
+
+
+
+
    +
+
+ + + Show Gist options + + + +
+ +
+
+ +
+ + +
+ +
+
+ +
+ +
    +
  • + +
    + + + + + + +
    + +
    +
    + +
    + + +
    + +
    +
    + +
    + + +
    + + +
    + + + + +
    +
    + +
    +
  • +
  • + Save oscarotero/7749998 to your computer and use it in GitHub Desktop. + + +
  • +
+ +
+ + +
+ +
+ + + + + + +
+ +
+
+ +
+ + +
+ +
+
+ +
+ + +
+ + +
+ + + + +
+
+ +
+ +
+ Save oscarotero/7749998 to your computer and use it in GitHub Desktop. + + +
+ + +
+
+ + +
+
+ +
+
+ +
+ +
+
+
+
+ + Raw + + + +
+ +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
# Undo latest commit
git reset --soft HEAD^
+
# Undo the changes of a commit (creating a new commit)
git revert <commit>
+
# Undo latest merge (before push)
git reset --merge ORIG_HEAD
+
# Merge a branch using the version of the current branch in case of conflicts
git merge <branch> -s ours
+
# Discard changes for a particular file after commit
git reset HEAD <file>
+
# Unstage the current staged changes
git reset
+
# Create, fetch a remote branch and switch to it
git checkout --track <remote>/<branch>
+
# Remove a file from git but not from disc
git rm --cached <file>
+
# Reapply an old commit again
git cherry-pick <commit>
+
# Ignore the changes of a file
git update-index --assume-unchanged <file>
+
# Not ignore the changes of a file
git update-index --no-assume-unchanged <file>
+
# List all "assume-unchanged" files
git ls-files -v|grep '^h'
+
# Display who did the latest change in each line (ignoring whitespaces)
git blame <filename> -w
+
# Remove all local branches removed in remote
git fetch origin --prune
+
# Remove untracked local files
git clean -f
+
# Remove untracked local files and folders
git clean -fd
+
# Remove remote branch
git push <remote> --delete <branch>
+
# Go to an old commit
git read-tree <commit>
+
# Use the ~/.gitignore file to ignore globally certain files
git config --global core.excludesfile '~/.gitignore'
+
+ + +
+ +
+
+ + + +
+
+
+ + + + + +
+
+ +
+ +
+
+ + Sign up for free + to join this conversation on GitHub. + Already have an account? + Sign in to comment + + + +
+
+
+
+
+
+
+ +
+
+ +
+ +
+

Footer

+ + + + +
+
+ + + + + © 2024 GitHub, Inc. + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +' +]; diff --git a/tests/cache/github.com.benbalter-dc-wifi-social-blob-master-bars.geojson.php b/tests/cache/github.com.benbalter-dc-wifi-social-blob-master-bars.geojson.php new file mode 100644 index 00000000..5570a25e --- /dev/null +++ b/tests/cache/github.com.benbalter-dc-wifi-social-blob-master-bars.geojson.php @@ -0,0 +1,1269 @@ + [ + 'server' => [ + 'GitHub.com' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:21:57 GMT' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'vary' => [ + 'X-PJAX, Accept-Encoding, Accept, X-Requested-With' + ], + 'etag' => [ + 'W/"9e2e7c708c636e14e8ca569c050e38c7"' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains; preload' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '0' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'expect-ct' => [ + 'max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"' + ], + 'content-security-policy' => [ + 'default-src \'none\'; base-uri \'self\'; block-all-mixed-content; connect-src \'self\' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events wss://alive.github.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com online.visualstudio.com/api/v1/locations; font-src github.githubassets.com; form-action \'self\' github.com gist.github.com; frame-ancestors \'none\'; frame-src render.githubusercontent.com; img-src \'self\' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com secured-user-images.githubusercontent.com/ *.githubusercontent.com; manifest-src \'self\'; media-src github.com user-images.githubusercontent.com/; script-src github.githubassets.com; style-src \'unsafe-inline\' github.githubassets.com; worker-src github.com/socket-worker-3f088aa2.js gist.github.com/socket-worker-3f088aa2.js' + ], + 'content-encoding' => [ + 'gzip' + ], + 'set-cookie' => [ + '_gh_sess=v2%2BrL5Zk1WvvCYtgyLSQLI4hNpX%2BVZV2gtRMsGqLQf65UW23S0fO%2BeIyd8w79%2BrT9XB9JXwvlIChzYu2CTaMsqc5zn%2BpE0ZgZQt%2BhAqh6%2FWyaXbKv%2FyCm9JA2rPogQvxud%2BKlaJk14I2u3JuhUR9%2FT0Z9wGhP1m7aO8fEHD1L5xzwGnlDSPt3rn5Jkz3oPMC42JMN86mQUtnhva6zofA%2FXOGkwtEfV%2B3Kwbmi6suCpIIKRwR4ND%2FPXYyWIgQUx80iti5QwhWzhPwY9QHNGjuKw%3D%3D--s22AVwf6Cf9gb63C--zKn5hoh58OmOPZpnOzxgfQ%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax', + '_octo=GH1.1.1526972749.1617549716; Path=/; Domain=github.com; Expires=Mon, 04 Apr 2022 15:21:56 GMT; Secure; SameSite=Lax', + 'logged_in=no; Path=/; Domain=github.com; Expires=Mon, 04 Apr 2022 15:21:56 GMT; HttpOnly; Secure; SameSite=Lax' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'x-github-request-id' => [ + 'CF20:EBE4:16E953C:18338CA:6069D994' + ], + 'Content-Location' => [ + 'https://github.com/benbalter/dc-wifi-social/blob/master/bars.geojson' + ], + 'X-Request-Time' => [ + '0.464 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dc-wifi-social/bars.geojson at master · benbalter/dc-wifi-social · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + +
+ +
+ +
+

+ + + / + + dc-wifi-social + + +

+ + +
+ + + +
+ + +
+ + +
+
+ + + + + +
+ + + + Permalink + + + +
+ +
+
+ + + master + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + + Go to file + + +
+ + +
+
+
+ + + +
+ +
+
+ + @obscurerichard + +
+ + + + + + +
+
+ + Latest commit + 98369bb + Oct 19, 2015 + + + + + + History + + +
+
+ +
+ +
+
+ + + 13 + + contributors + + +
+ +

+ Users who have contributed to this file +

+
+ + + + + + +
+
+ + + @benbalter + + @obscurerichard + + @sroberts + + @geobrando + + @yurivictor + + @opattison + + @nikAleksandr + + @nacin + + @mikelmaron + + @malmckay + + @johnpbloch + + @dinomite + + + + +
+
+ + + + + + + +
+ +
+
+ + + 459 lines (459 sloc) + + 9.5 KB +
+ +
+ + +
+ Raw + Blame +
+ + +
+
+ + + +
+ +
+
+ + + + +
Sorry, something went wrong. Reload?
+
Sorry, we cannot display this file.
+
Sorry, this file is invalid so it cannot be displayed.
+ +
+
+ +
+ +
+ + + +
+ + +
+ + +
+
+ + +
+ + + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/github.com.oscarotero-embed-blob-master-composer.json.php b/tests/cache/github.com.oscarotero-embed-blob-master-composer.json.php new file mode 100644 index 00000000..0f769be5 --- /dev/null +++ b/tests/cache/github.com.oscarotero-embed-blob-master-composer.json.php @@ -0,0 +1,1431 @@ + [ + 'server' => [ + 'GitHub.com' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:23:15 GMT' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'vary' => [ + 'X-PJAX, Accept-Encoding, Accept, X-Requested-With' + ], + 'etag' => [ + 'W/"ef26dd5013b9706b964fc4c367c4f92b"' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains; preload' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '0' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'expect-ct' => [ + 'max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"' + ], + 'content-security-policy' => [ + 'default-src \'none\'; base-uri \'self\'; block-all-mixed-content; connect-src \'self\' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events wss://alive.github.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com online.visualstudio.com/api/v1/locations; font-src github.githubassets.com; form-action \'self\' github.com gist.github.com; frame-ancestors \'none\'; frame-src render.githubusercontent.com; img-src \'self\' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com secured-user-images.githubusercontent.com/ *.githubusercontent.com; manifest-src \'self\'; media-src github.com user-images.githubusercontent.com/; script-src github.githubassets.com; style-src \'unsafe-inline\' github.githubassets.com; worker-src github.com/socket-worker-3f088aa2.js gist.github.com/socket-worker-3f088aa2.js' + ], + 'content-encoding' => [ + 'gzip' + ], + 'set-cookie' => [ + '_gh_sess=vifcNZcjbeKXiHoKgFoXPrhU73APnO8QIA0GiNWPEBgpTgDHaS0EuZXiD%2BFnPWCMAlx0g%2BE%2BmZS5zi%2BMEueSIVh5U%2F76p7wNjUfLkSW5Uf2HegJjQflX1IP1AIZnVOCYwzTrTqyYaVssSIlHy9gxFrx%2FoqvZwj8HexaHZHww1LJ8ASYgmEGbP7KtEIHX%2Ff4kqlvDmNjuNGx8r132g8%2FPGVdzb6H4feA%2FrtDcwCtrFGcbLdI9dx3JksJ12PT54yaPTNQa%2Fr2cr9a%2F4ZaJjXkhpA%3D%3D--eDIEZjaz6YPDnQEs--d%2BkLZLWoZOM1bAb4luLwdw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax', + '_octo=GH1.1.1856600872.1617549794; Path=/; Domain=github.com; Expires=Mon, 04 Apr 2022 15:23:14 GMT; Secure; SameSite=Lax', + 'logged_in=no; Path=/; Domain=github.com; Expires=Mon, 04 Apr 2022 15:23:14 GMT; HttpOnly; Secure; SameSite=Lax' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'x-github-request-id' => [ + 'CFCB:F09E:3FE1060:41F5E4A:6069D9E2' + ], + 'Content-Location' => [ + 'https://github.com/oscarotero/Embed/blob/master/composer.json' + ], + 'X-Request-Time' => [ + '0.471 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Embed/composer.json at master · oscarotero/Embed · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + + + +
+
+ + + + + +
+ + + + Permalink + + + +
+ +
+
+ + + master + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + + Go to file + + +
+ + +
+
+
+ + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + + +
+ +
+
+ + 72 lines (72 sloc) + + 1.88 KB +
+ +
+ +
+ Raw + Blame +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{
"name": "embed/embed",
"type": "library",
"description": "PHP library to retrieve page info using oembed, opengraph, etc",
"keywords": [
"oembed",
"opengraph",
"twitter cards",
"embed",
"embedly"
],
"homepage": "https://github.com/oscarotero/Embed",
"license": "MIT",
"authors": [
{
"name": "Oscar Otero",
"email": "oom@oscarotero.com",
"homepage": "http://oscarotero.com",
"role": "Developer"
}
],
"support": {
"email": "oom@oscarotero.com",
"issues": "https://github.com/oscarotero/Embed/issues"
},
"require": {
"php": "^7.4|^8",
"ext-curl": "*",
"ext-dom": "*",
"ext-json": "*",
"ext-mbstring": "*",
"composer/ca-bundle": "^1.0",
"oscarotero/html-parser": "^0.1.4",
"psr/http-message": "^1.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"ml/json-ld": "^1.1"
},
"require-dev": {
"phpunit/phpunit": "^9.0",
"friendsofphp/php-cs-fixer": "^2.0",
"nyholm/psr7": "^1.2",
"oscarotero/php-cs-fixer-config": "^1.0",
"brick/varexporter": "^0.3.1",
"symfony/css-selector": "^5.0"
},
"suggest": {
"symfony/css-selector": "If you want to get elements using css selectors"
},
"autoload": {
"psr-4": {
"Embed\\\\": "src"
},
"files": [
"src/functions.php"
]
},
"autoload-dev": {
"psr-4": {
"Embed\\\\Tests\\\\": "tests/"
}
},
"scripts": {
"demo": "php -S localhost:8888 demo/index.php",
"test": "phpunit",
"cs-fix": "php-cs-fixer fix",
"update-resources": [
"php scripts/update-oembed.php",
"php scripts/update-suffix.php"
]
}
}
+ + + +
+ +
+ + + +
+ + +
+ + +
+
+ + +
+ + + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/github.com.skalnik-secret-bear-clip-blob-master-stl-clip.stl.php b/tests/cache/github.com.skalnik-secret-bear-clip-blob-master-stl-clip.stl.php new file mode 100644 index 00000000..3774edf6 --- /dev/null +++ b/tests/cache/github.com.skalnik-secret-bear-clip-blob-master-stl-clip.stl.php @@ -0,0 +1,1130 @@ + [ + 'server' => [ + 'GitHub.com' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:37 GMT' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'vary' => [ + 'X-PJAX, Accept-Encoding, Accept, X-Requested-With' + ], + 'etag' => [ + 'W/"179f1299c31b5b79efa462c4b1eea7b8"' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains; preload' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '0' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'expect-ct' => [ + 'max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"' + ], + 'content-security-policy' => [ + 'default-src \'none\'; base-uri \'self\'; block-all-mixed-content; connect-src \'self\' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events wss://alive.github.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com online.visualstudio.com/api/v1/locations; font-src github.githubassets.com; form-action \'self\' github.com gist.github.com; frame-ancestors \'none\'; frame-src render.githubusercontent.com; img-src \'self\' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com secured-user-images.githubusercontent.com/ *.githubusercontent.com; manifest-src \'self\'; media-src github.com user-images.githubusercontent.com/; script-src github.githubassets.com; style-src \'unsafe-inline\' github.githubassets.com; worker-src github.com/socket-worker-3f088aa2.js gist.github.com/socket-worker-3f088aa2.js' + ], + 'content-encoding' => [ + 'gzip' + ], + 'set-cookie' => [ + '_gh_sess=JS4OjzH9K8S5s1AcaFMJGCvfkag8cS2g5jE%2F%2BMlnkOAerMq9CGoKH1AdDFk0pZr8AzqxQexRKh3jZ9lEu46A3QBllK4I9RKZI9Hcr9N8RffeCP3Z0ZvbsufqUMA%2F6ECleamCG5VDbWiU8e%2BF%2BWwoW0ONiuUmv0rf4%2BMFCvEY84k3LCrYd5tZxwVWtx4Ye5pHbpyFv67c1zuv1DVZfbFezYidDxZWId0ialVqG36OFj40z3zzumuQepUuE4yRp%2Fziu7gdI0rud38u2Ys1jYlhTg%3D%3D--6Hwa2ICk3t37%2B1L%2B--jj8WGA%2BymSJOM78YPWlM7g%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax', + '_octo=GH1.1.1441121924.1617549757; Path=/; Domain=github.com; Expires=Mon, 04 Apr 2022 15:22:37 GMT; Secure; SameSite=Lax', + 'logged_in=no; Path=/; Domain=github.com; Expires=Mon, 04 Apr 2022 15:22:37 GMT; HttpOnly; Secure; SameSite=Lax' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'x-github-request-id' => [ + 'CF7A:11318:28305B6:29BD9FF:6069D9BC' + ], + 'Content-Location' => [ + 'https://github.com/skalnik/secret-bear-clip/blob/master/stl/clip.stl' + ], + 'X-Request-Time' => [ + '0.457 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + secret-bear-clip/clip.stl at master · skalnik/secret-bear-clip · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + + + +
+
+ + + + + +
+ + + + Permalink + + + +
+ +
+
+ + + master + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + + Go to file + + +
+ + +
+
+
+ + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + + +
+ +
+
+ + 7.5 KB +
+ +
+ +
+ Download +
+ +
+ + + + +
+ +
+
+
+ + + +
+ +
+
+ + + + +
Sorry, something went wrong. Reload?
+
Sorry, we cannot display this file.
+
Sorry, this file is invalid so it cannot be displayed.
+ +
+
+ +
+ +
+ + + +
+ + +
+ + +
+
+ + +
+ + + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/he-who-photographs-rather-ok.tumblr.com.post-165326273724.php b/tests/cache/he-who-photographs-rather-ok.tumblr.com.post-165326273724.php new file mode 100644 index 00000000..42b0409f --- /dev/null +++ b/tests/cache/he-who-photographs-rather-ok.tumblr.com.post-165326273724.php @@ -0,0 +1,659 @@ + [ + 'server' => [ + 'openresty', + 'openresty' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:58 GMT', + 'Mon, 10 Jun 2024 15:58:59 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8', + 'text/html; charset=UTF-8' + ], + 'content-length' => [ + '0', + '13503' + ], + 'connection' => [ + 'keep-alive' + ], + 'x-rid' => [ + '77180a9f6246f6207ce43a44df8a4068', + 'f363b371c810b88fc1a809dbdbc73dbd' + ], + 'p3p' => [ + 'CP="Tumblr\'s privacy policy is available here: https://www.tumblr.com/policy/en/privacy"', + 'CP="Tumblr\'s privacy policy is available here: https://www.tumblr.com/policy/en/privacy"' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-xss-protection' => [ + '1; mode=block', + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'strict-transport-security' => [ + 'max-age=15552001', + 'max-age=15552001' + ], + 'location' => [ + 'https://he-who-photographs-rather-ok.tumblr.com/post/165326273724' + ], + 'x-ua-compatible' => [ + 'IE=Edge,chrome=1', + 'IE=Edge,chrome=1' + ], + 'x-ua-device' => [ + 'desktop', + 'desktop' + ], + 'vary' => [ + 'X-UA-Device, Accept HTTP/2 200', + 'X-UA-Device, Accept, Accept-Encoding' + ], + 'x-tumblr-user' => [ + 'he-who-photographs-rather-ok' + ], + 'x-tumblr-pixel-0' => [ + 'https://px.srvcs.tumblr.com/impixu?T=1718035139&J=eyJ0eXBlIjoidXJsIiwidXJsIjoiaHR0cDovL2hlLXdoby1waG90b2dyYXBocy1yYXRoZXItb2sudHVtYmxyLmNvbS9wb3N0LzE2NTMyNjI3MzcyNCIsInJlcXR5cGUiOjAsInJvdXRlIjoiL3Bvc3QvOmlkIn0=&U=DHEFECIPPP&K=85898e167eb3362d289dc8b297579abc080f6137309260d1bd8168a34041b0e4--https://px.srvcs.tumblr.com/impixu?T=1718035139&J=eyJ0eXBlIjoicG9zdCIsInVybCI6Imh0dHA6Ly9oZS13aG8tcGhvdG9ncmFwaHMtcmF0aGVyLW9rLnR1bWJsci5jb20vcG9zdC8xNjUzMjYyNzM3MjQiLCJyZXF0eXBlIjowLCJyb3V0ZSI6Ii9w' + ], + 'x-tumblr-pixel-1' => [ + 'b3N0LzppZCIsInBvc3RzIjpbeyJwb3N0aWQiOiIxNjUzMjYyNzM3MjQiLCJibG9naWQiOjEwNTU5MTE5MCwic291cmNlIjozM31dfQ==&U=CANIBNNONG&K=408537bbdf64b1f2cd50c0e369f43f8802055b87b8c590d6e8e08e8b6bdbd2ba' + ], + 'x-tumblr-pixel' => [ + '2' + ], + 'link' => [ + '; rel=icon' + ], + 'content-encoding' => [ + 'br' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'Content-Location' => [ + 'https://he-who-photographs-rather-ok.tumblr.com/post/165326273724' + ], + 'X-Request-Time' => [ + '0.904 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + +
+ + +
+ + + + + He-who-photographs-rather-OK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + +
+ + +
Usually minimal editing. Also effort
+ + + + + + Install Theme + + +
+ + + +
+ +
+ + +
+ + + +
+ + + + + + + + + + +
+ +
+ + + + + + + + + +
+ + + +
+
+ + + + 14th Sep 2017 + + + + + + 1,027 notes + + + +
+ + + +
+ + +
+ + + +
  1. manake511 reblogged this from phoelipop
  2. phoelipop reblogged this from he-who-photographs-rather-ok
  3. kuruptwolf reblogged this from he-who-photographs-rather-ok
  4. infj-arli reblogged this from he-who-photographs-rather-ok
  5. dharmabeatdownblog reblogged this from wastelandruckus
  6. wastelandruckus reblogged this from he-who-photographs-rather-ok
  7. afaceinside reblogged this from he-who-photographs-rather-ok
  8. redpandarascal reblogged this from redpandarascal
  9. victorydoll reblogged this from he-who-photographs-rather-ok
  10. corvidcrimes reblogged this from he-who-photographs-rather-ok
  11. sir-wuffalot reblogged this from he-who-photographs-rather-ok
  12. sionnach--ruadh reblogged this from he-who-photographs-rather-ok
  13. chaotic-cheshire reblogged this from he-who-photographs-rather-ok
  14. he-who-photographs-rather-ok posted this
+ + +
+ + + + + +
+ + + + + + + + + + + + +' +]; diff --git a/tests/cache/i.imgur.com.x6rkcc5.jpg.php b/tests/cache/i.imgur.com.x6rkcc5.jpg.php new file mode 100644 index 00000000..c231b997 --- /dev/null +++ b/tests/cache/i.imgur.com.x6rkcc5.jpg.php @@ -0,0 +1,96 @@ + [ + 'connection' => [ + 'close' + ], + 'content-length' => [ + '0', + '565369' + ], + 'retry-after' => [ + '0' + ], + 'location' => [ + 'https://i.imgur.com/X6rkCc5.jpg' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:47 GMT', + 'Mon, 10 Jun 2024 15:58:47 GMT' + ], + 'x-served-by' => [ + 'cache-mad2200140-MAD', + 'cache-iad-kiad7000051-IAD, cache-mad2200135-MAD' + ], + 'x-cache' => [ + 'HIT', + 'Miss from cloudfront, HIT, HIT' + ], + 'x-cache-hits' => [ + '0', + '3, 0' + ], + 'x-timer' => [ + 'S1718035128.759419,VS0,VE0', + 'S1718035128.831783,VS0,VE1' + ], + 'strict-transport-security' => [ + 'max-age=300', + 'max-age=300' + ], + 'access-control-allow-methods' => [ + 'GET, OPTIONS', + 'GET, OPTIONS' + ], + 'access-control-allow-origin' => [ + '*', + '*' + ], + 'server' => [ + 'cat factory 1.0 HTTP/2 200', + 'cat factory 1.0' + ], + 'content-type' => [ + 'image/jpeg' + ], + 'last-modified' => [ + 'Wed, 21 Jan 2015 15:15:05 GMT' + ], + 'etag' => [ + '"0ea794bbaf4a18a9dafadb05a8fb5ba7"' + ], + 'x-amz-storage-class' => [ + 'STANDARD_IA' + ], + 'x-amz-cf-pop' => [ + 'IAD89-P1' + ], + 'x-amz-cf-id' => [ + '10DGv7ZcAIqQI7G6jGcHt1Ch4v8jNH0NBkczbt6mQMxJ0gWALFeEPQ==' + ], + 'cache-control' => [ + 'public, max-age=31536000' + ], + 'age' => [ + '824835' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'Content-Location' => [ + 'https://i.imgur.com/X6rkCc5.jpg' + ], + 'X-Request-Time' => [ + '0.118 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '' +]; diff --git a/tests/cache/ideone.com.whjntg.php b/tests/cache/ideone.com.whjntg.php new file mode 100644 index 00000000..9c3ca7a4 --- /dev/null +++ b/tests/cache/ideone.com.whjntg.php @@ -0,0 +1,779 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:10 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'content-length' => [ + '8369' + ], + 'set-cookie' => [ + 'PHPSESSID=g9103qksgd9g7b6m7jgpupqci2; path=/' + ], + 'expires' => [ + 'Thu, 19 Nov 1981 08:52:00 GMT' + ], + 'cache-control' => [ + 'no-store, no-cache, must-revalidate' + ], + 'pragma' => [ + 'no-cache' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'Content-Location' => [ + 'https://ideone.com/Whjntg' + ], + 'X-Request-Time' => [ + '0.875 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + Whjntg - Online C Compiler & Debugging Tool - Ideone.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + + + + +
+
+
+ +
+
+
+ + +
+ + + + + + +
+ + + + + + + + +
+ + + + + + + fork + + download + + + + + +
+ + copy +
+
+ + + +
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3.  
  4. int main() {
  5. int n;
  6. char *s = malloc(20*sizeof(char));
  7. printf("%d\\n",sizeof(s));
  8. sscanf(s,"%d",&n);
  9. printf("%d, %d\\n",sizeof(n),n+9);
  10. }
+ + + + + + +
+ + + +
+ + + Success + + #stdin + #stdout + + 0s 2244KB + + + +
+ + + + + + + + +
+ + stdin +
+ + copy +
+
+ +
27
+ +
+ + +
+ + + + + + + stdout +
+ + copy +
+
+
+
4
+4, -1218449834
+
+
+ + + + +
+ + + + + + + + +
+ + + +
+ + +
+ + + + + +
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +' +]; diff --git a/tests/cache/imageshack.com.i-ip7wo0v7j.php b/tests/cache/imageshack.com.i-ip7wo0v7j.php new file mode 100644 index 00000000..875b299e --- /dev/null +++ b/tests/cache/imageshack.com.i-ip7wo0v7j.php @@ -0,0 +1,150 @@ + [ + 'server' => [ + 'nginx/1.2.8', + 'nginx/1.2.8', + 'nginx/1.2.8' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:08 GMT', + 'Mon, 10 Jun 2024 15:59:08 GMT', + 'Mon, 10 Jun 2024 15:59:09 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html', + 'image/jpeg' + ], + 'content-length' => [ + '160', + '26', + '43630' + ], + 'connection' => [ + 'keep-alive', + 'keep-alive' + ], + 'location' => [ + 'https://imageshack.com/d/ip7wO0v7j', + 'https://imagizer.imageshack.com/img673/0/7wO0v7.jpg' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes', + 'bytes' + ], + 'x-varnish' => [ + '684845256', + '1417234088', + '3637154758 3606704929' + ], + 'age' => [ + '0', + '0' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish' + ], + 'x-varnish-hits' => [ + '0', + '0', + '34' + ], + 'x-varnish-ip' => [ + '208.94.3.34', + '208.94.3.33', + '38.99.77.68' + ], + 'x-varnish-port' => [ + '17001', + '17001', + '17001' + ], + 'vary' => [ + 'User-Agent HTTP/1.1 301 Moved Permanently', + 'Accept-Encoding, User-Agent HTTP/2 200' + ], + 'x-powered-by' => [ + 'PHP/5.2.9' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-original-quality' => [ + '80' + ], + 'x-original-response-code' => [ + '200' + ], + 'x-original-filesize' => [ + '54800' + ], + 'x-origin-fetch-time' => [ + '72' + ], + 'x-original-resolution' => [ + '500x500' + ], + 'x-imagizer-host' => [ + 'imageshack.imagizer.com' + ], + 'xkey' => [ + 'imageshack.imagizer.com' + ], + 'etag' => [ + 'c4ca4238a0b923820dcc509a6f75849b' + ], + 'x-ops' => [ + '{"quality":60}' + ], + 'access-control-allow-methods' => [ + 'GET, POST, OPTIONS, HEAD', + 'GET, POST, OPTIONS', + 'GET, POST, OPTIONS', + 'GET, POST, OPTIONS' + ], + 'access-control-allow-headers' => [ + 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Length,X-Original-Filesize,X-Original-Resolution,X-CSRF-TOKEN', + 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since', + 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since', + 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since' + ], + 'access-control-expose-headers' => [ + 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Length,X-Original-Filesize,X-Original-Resolution,X-CSRF-TOKEN' + ], + 'x-cache-hits' => [ + '0' + ], + 'access-control-allow-credentials' => [ + 'true', + 'true', + 'true' + ], + 'cache-control' => [ + 'public, max-age=1979132' + ], + 'akamai-cache-status' => [ + 'Hit from child' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'Content-Location' => [ + 'https://imagizer.imageshack.com/img673/0/7wO0v7.jpg' + ], + 'X-Request-Time' => [ + '1.305 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '' +]; diff --git a/tests/cache/infogr.am.7743c36a-f3ca-4465-9a80-a8abbd5d8dc4.php b/tests/cache/infogr.am.7743c36a-f3ca-4465-9a80-a8abbd5d8dc4.php new file mode 100644 index 00000000..f673fd13 --- /dev/null +++ b/tests/cache/infogr.am.7743c36a-f3ca-4465-9a80-a8abbd5d8dc4.php @@ -0,0 +1,4501 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:48 GMT', + 'Mon, 10 Jun 2024 15:58:48 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '162' + ], + 'location' => [ + 'https://infogram.com/7743c36a-f3ca-4465-9a80-a8abbd5d8dc4' + ], + 'server' => [ + 'nginx HTTP/2 200', + 'nginx' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-dns-prefetch-control' => [ + 'off' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'referrer-policy' => [ + 'no-referrer' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'etag' => [ + 'W/"3f7a9-fzzkeqtbvZcHL6wys8hFeUEGCjo"' + ], + 'set-cookie' => [ + 'ig_session=s%3A9e5o8X5HVNIDjjf6H4nDHiNxIq8r5IPu.HaN%2FrKZnzHEq6p5kMCtIBOGYOS6Z4ufxjEJODNHkElE; Domain=.infogram.com; Path=/; HttpOnly; Secure' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://infogram.com/7743c36a-f3ca-4465-9a80-a8abbd5d8dc4' + ], + 'X-Request-Time' => [ + '0.563 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + Frost Bank Advisors (online graphic) by Archive - Infogram + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/infogram.com.oembed.8359659f481fe55276b250ff48903750.php b/tests/cache/infogram.com.oembed.8359659f481fe55276b250ff48903750.php new file mode 100644 index 00000000..9dc4cb2f --- /dev/null +++ b/tests/cache/infogram.com.oembed.8359659f481fe55276b250ff48903750.php @@ -0,0 +1,61 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:48 GMT' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'server' => [ + 'nginx' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-dns-prefetch-control' => [ + 'off' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'referrer-policy' => [ + 'no-referrer' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'etag' => [ + 'W/"3ea-w0hv6K7MtO0BQ8VOp+dPNN3LXI0"' + ], + 'set-cookie' => [ + 'ig_session=s%3A3_ukJEHCDdrkbwTN0Pn4oRLG_NwKLQdN.KKvCfnVCxy5Y03qQ94Ak0Te2Htp9H47HuD6kE%2F2TqoA; Domain=.infogram.com; Path=/; HttpOnly; Secure' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://infogram.com/oembed/?url=https%3A%2F%2Finfogram.com%2Ffrost-bank-advisors-online-graphic-1g8e205xdj03pod' + ], + 'X-Request-Time' => [ + '0.249 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"rich","provider_url":"https://infogram.com/","provider_name":"Infogram","description":"","title":"Frost Bank Advisors (online graphic)","thumbnail_url":"https://infogram-thumbs-1024.s3-eu-west-1.amazonaws.com/4e31a649-39af-4bfd-a6a9-384e727e36e2.jpg","uri":"https://infogram.com/frost-bank-advisors-online-graphic-1g8e205xdj03pod","html":"
","width":550,"height":600,"author_url":"https://infogram.com/archivef","author_name":"Archive"}' +]; diff --git a/tests/cache/jeanjean.bandcamp.com.track-coquin-l-l-phant.php b/tests/cache/jeanjean.bandcamp.com.track-coquin-l-l-phant.php new file mode 100644 index 00000000..3ce7e071 --- /dev/null +++ b/tests/cache/jeanjean.bandcamp.com.track-coquin-l-l-phant.php @@ -0,0 +1,2931 @@ + [ + 'connection' => [ + 'keep-alive' + ], + 'content-length' => [ + '174' + ], + 'server' => [ + 'nginx', + 'nginx' + ], + 'location' => [ + 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant' + ], + 'set-cookie' => [ + 'BACKENDID3=flexocentral-q910-4; path=/; Secure', + 'session=1%09bp%3A1%09t%3A1718035021%09r%3A%5B%2288900657t2592086951t2592086951x1718035111%22%5D; domain=.bandcamp.com; path=/; expires=Thu, 25 Jul 2024 15:57:01 GMT' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:30 GMT', + 'Mon, 10 Jun 2024 15:58:31 GMT' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish' + ], + 'x-served-by' => [ + 'cache-mad2200133-MAD', + 'cache-mad2200146-MAD' + ], + 'x-cache' => [ + 'MISS', + 'MISS' + ], + 'x-cache-hits' => [ + '0', + '0' + ], + 'x-timer' => [ + 'S1718035111.733513,VS0,VE215 HTTP/2 200', + 'S1718035111.083684,VS0,VE455' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'link' => [ + '; rel="canonical"' + ], + 'cache-control' => [ + 'no-cache, no-store' + ], + 'content-security-policy' => [ + 'base-uri \'none\'; object-src \'none\'; report-uri https://bandcamp.com/api/cspreport/1/violation; script-src http: https: \'nonce-TiBin7PvaDphlW30KQg+gw==\' \'report-sample\' \'strict-dynamic\'' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'Content-Location' => [ + 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant' + ], + 'X-Request-Time' => [ + '0.856 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + Coquin L'éléphant | Jean Jean + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + We’ve updated our Terms of Use to reflect our new entity name and address. You can review the changes here. +
+
+ + We’ve updated our Terms of Use. You can review the changes here. +
+ + + + +
+ + + + + + +
+
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+

+ Coquin L'éléphant + +

+

+ + from + Symmetry by + + + Jean Jean + + + + +

+ + + + + +
+ +
+ + + +
+ + + + + +
+ + + + + + + + + +
+ +
+
+ + + +
+ + + + + + + + + + +
+
+
+
+ + + + + + / + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + +
    + + + + + + + + + + + + + + + + +
  • +

    + + + + +
    Streaming + Download
    + +

    + + +
    + Includes unlimited streaming via the free Bandcamp app, plus high-quality download in MP3, FLAC and more. + +
    + + + + + + + + + + + + + + +
    + + Purchasable with gift card +
    + + +
    + + +

    + +   + + + + + €1 + EUR +  or more + + +

    + + + + +

    +   +

    + +
    +
  • + + + + + + + + + + + +
  • + + + + + + +

    + + + + + + + + + + + + 12" Vinyl + + + + + + +
    + + + + + + + Record/Vinyl + Digital Album + + + + +
    + +

    + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + Includes unlimited streaming of Symmetry + via the free Bandcamp app, plus high-quality download in MP3, FLAC and more. + + + + + + +
    + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +

    Sold Out

    + + +
    + +
  • + + + + + + + + + + + + + + + + + + + +
  • + + +
+ + + + + + + + + + + + + + +

credits

+
+ + + + + + + + + + + + + + + + + + from Symmetry, + + + + + + released September 14, 2013 + + + + + +
+ + + + + + + +

license

+
+ + all rights reserved + + + +
+ +
+
+ + + + +

tags

+ + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+
+ + + +
+
+
+
+ + + + + + +
+

about

+ + + +
+ +
+ + + +

+ Jean Jean + Sept Sorts, France +

+ + + + + + +
+ + +

« On stage, JEAN JEAN is a mirror to their music : deeply intense, smiling and sharing an outra- geous joie-de-vivre. It all seems so simple, but when it builds up, they take you far, very far away » (Christophe Ehrwein)

+ + +
+ + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ +
+
+
+
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

contact / help

+ + + +

+ + Contact Jean Jean + +

+ + +

Streaming and
Download help

+ + + + + +

Redeem code

+ + + + + +

+ + + Report this track or account + + +

+ + + +
+ +
+ +
+
+ +
+ + +
+
+ +
+ +
+

Jean Jean recommends:

+
    + + + + + + + +
+
+ +
+

+ + If you like Jean Jean, you may also like: + +

+
    + + + + + + + + + + + + + +
+
+
+ + +
+ + + + + + + + +
+ + + +
+ + + + +   + +
+ + + +
+ + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/jsbin.com.oembed.10c0d2332368898b06548ab132206584.php b/tests/cache/jsbin.com.oembed.10c0d2332368898b06548ab132206584.php new file mode 100644 index 00000000..3045dbdf --- /dev/null +++ b/tests/cache/jsbin.com.oembed.10c0d2332368898b06548ab132206584.php @@ -0,0 +1,48 @@ + [ + 'server' => [ + 'nginx' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:27:26 GMT' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'content-length' => [ + '231' + ], + 'connection' => [ + 'keep-alive' + ], + 'set-cookie' => [ + 'jsbin=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT', + 'session=eyJ2ZXJzaW9uIjoiNC4xLjgiLCJjc3JmU2VjcmV0IjoiU01XR1hJRTVMX1g3c0RHeVZkVEg5b0ZtIn0=; path=/; expires=Mon, 04 Apr 2022 15:27:26 GMT; domain=.jsbin.com; httponly', + 'session.sig=sNcS-dMUkPGHq2dJrTA4yOHTYrc; path=/; expires=Mon, 04 Apr 2022 15:27:26 GMT; domain=.jsbin.com; httponly' + ], + 'x-robots-tag' => [ + 'nofollow' + ], + 'etag' => [ + 'W/"e7-zdqGtjQFwMuocE+sKf4uaTPn5bk"' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-route' => [ + 'node' + ], + 'Content-Location' => [ + 'http://jsbin.com/oembed?url=http%3A%2F%2Foutput.jsbin.com%2Fvonesu%2F10&format=json' + ], + 'X-Request-Time' => [ + '0.349 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"rich","version":"1.0","title":"JS Bin","url":"http://output.jsbin.com/vonesu/10","width":320,"height":240,"html":""}' +]; diff --git a/tests/cache/jsfiddle.net.zhm5rjnz.php b/tests/cache/jsfiddle.net.zhm5rjnz.php new file mode 100644 index 00000000..91235a3f --- /dev/null +++ b/tests/cache/jsfiddle.net.zhm5rjnz.php @@ -0,0 +1,2043 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:49 GMT', + 'Mon, 10 Jun 2024 15:58:49 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://jsfiddle.net/zhm5rjnz/' + ], + 'vary' => [ + 'Origin', + 'Accept, Origin' + ], + 'cf-cache-status' => [ + 'DYNAMIC', + 'DYNAMIC' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=smYyWClKo8oEfoqwDtz8RbGTzhdwJhBGoEkAVlJHdwoC0%2FRViIXnRBhn5D0x52YeiXtynn8ns9ymj8MLjvuZoiY3Lrxkhbu97ahRBAlOsD%2FFi4240JJlZQqecO9KbZA%3D"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=ZQf9%2BcXUhP%2B8TWx3CzDToVxYO%2FXMrXTmrublBYml0mvl0UT3EM1rhxBT3bS1hQXwqEMrBm9cQnBa1MOTfjwmcgckWlBrCp%2BJePlRFK5Rj0cOcOsZy7jIVb4aa085SIs%3D"}],"group":"cf-nel","max_age":604800}' + ], + 'nel' => [ + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' + ], + 'server' => [ + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a90a40bba86bc-MAD', + '891a90a5cc6c3c9e-CDG' + ], + 'alt-svc' => [ + 'h2=":443"; ma=60 HTTP/2 200', + 'h3=":443"; ma=86400' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'set-cookie' => [ + 'csrftoken=h4BPAI4qgmfUF5gMylwoRYfVu5rDEId4mnPcY%2FK9FAtqwZFjzPaznl2TXMBtUAb%2Ffdr3iK%2BXVM8DdORXVZzjQg%3D%3D; path=/; secure', + '_jsfiddle_session=FXaU2Fprh8TikhvBBkj2dLNXPwisA6kV78LzTrq1okZqd5sH9dGoCa%2B8DhDyBT%2FWYMr7wU4voNDiCgTBtZbHcmQ9r0HVW4BSRZu38cs3GzSD6W5m6aXZjPuli4yo9ofFkV2%2FQGdYXu9wCUnUyEKMY%2B1kYZeU9Kc8kHsXG822wE9Mw4fkU9%2Fo1bw3iQKsYv5EkPIYzUw%2BCUZRfmjmPW264UxjpulsZSLkFm0cvnnwx4VvefRLha4Caqowwcdi6RA%2FoEzHFnFnv78k6QbWpyckrV46uZRaSK%2FLBw%3D%3D--BjzsN4nNb%2Bm2%2F7z%2F--z0EI3ySac%2BbWtHrbwc5UXQ%3D%3D; path=/; secure; HttpOnly' + ], + 'x-request-id' => [ + '867cb413-f961-4762-9a75-3cf0de52f509' + ], + 'x-runtime' => [ + '0.092817' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://jsfiddle.net/zhm5rjnz/' + ], + 'X-Request-Time' => [ + '0.635 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Edit fiddle - JSFiddle - Code Playground + + + + +
+ + +
+

+ JSFiddle + +

+
+ + + + + + + + + + + + +
+ + + + + + + +
+
+ +
+ +
+
+ + + + + + + +
+ +
+ + + + +
+
+ + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/live.amcharts.com.cznjj.php b/tests/cache/live.amcharts.com.cznjj.php new file mode 100644 index 00000000..e266b071 --- /dev/null +++ b/tests/cache/live.amcharts.com.cznjj.php @@ -0,0 +1,200 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:29 GMT', + 'Mon, 10 Jun 2024 15:58:29 GMT', + 'Mon, 10 Jun 2024 15:58:29 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html', + 'text/html' + ], + 'content-length' => [ + '167' + ], + 'connection' => [ + 'keep-alive' + ], + 'cache-control' => [ + 'max-age=3600' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:58:29 GMT' + ], + 'location' => [ + 'https://live.amcharts.com/czNjJ', + 'https://live.amcharts.com/czNjJ/' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=VtzENtQNuDELnHKFxDH6W%2B9oSzhVjYav00pwarC%2BiNMZGML5KQaY5nZEf%2FEooMobRKOH1rkCZ0d3NyKiNlD5fXBpxz%2FJTo%2FKZV%2BigJ%2BBLAL451vjSSGMFasfQqunl%2Fq%2B6flX"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=RQtd%2FJf%2FCqGWHZTv7YQ5u1i6aNadW6XKlpi2xZYPAsy3vTPiguSzRLHPvJFvskhLQNBpEctImBIdXdKxjYglhsunaO6lfbpnf1qWg4MDmLM9lx%2BcAMu29HlA0E0VewClnhtU"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=ERbbJx9jroFM%2FeXUW7sqbXsbL8Ht48f%2BZChiumfPf2DXT64fyO1INe1HJPXbiacMkxHAeDtjR5voJEmpNJpqZbQWbop%2B2ue9NsRt1sv48b73C4FqCYMqx4yBPy127oAnHnSz"}],"group":"cf-nel","max_age":604800}' + ], + 'nel' => [ + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' + ], + 'vary' => [ + 'Accept-Encoding', + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare', + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a9027ad81f180-CDG', + '891a90285923f174-CDG HTTP/2 200', + '891a902afca2f174-CDG' + ], + 'alt-svc' => [ + 'h2=":443"; ma=60 HTTP/2 301' + ], + 'platform' => [ + 'hostinger', + 'hostinger' + ], + 'content-security-policy' => [ + 'upgrade-insecure-requests', + 'upgrade-insecure-requests' + ], + 'x-turbo-charged-by' => [ + 'LiteSpeed', + 'LiteSpeed' + ], + 'cf-cache-status' => [ + 'DYNAMIC', + 'DYNAMIC' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload', + 'max-age=31536000; includeSubDomains; preload' + ], + 'x-powered-by' => [ + 'PHP/5.5.38' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://live.amcharts.com/czNjJ/' + ], + 'X-Request-Time' => [ + '0.716 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + +Online Chart Maker | amCharts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +' +]; diff --git a/tests/cache/live.amcharts.com.oembed.97d95dea3f4167bb20bb4c88d620386a.php b/tests/cache/live.amcharts.com.oembed.97d95dea3f4167bb20bb4c88d620386a.php new file mode 100644 index 00000000..090002d4 --- /dev/null +++ b/tests/cache/live.amcharts.com.oembed.97d95dea3f4167bb20bb4c88d620386a.php @@ -0,0 +1,177 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:30 GMT', + 'Mon, 10 Jun 2024 15:58:30 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html' + ], + 'location' => [ + 'https://live.amcharts.com/oembed/?url=https%3A%2F%2Flive.amcharts.com%2FczNjJ%2F&format=json' + ], + 'platform' => [ + 'hostinger', + 'hostinger' + ], + 'content-security-policy' => [ + 'upgrade-insecure-requests', + 'upgrade-insecure-requests' + ], + 'x-turbo-charged-by' => [ + 'LiteSpeed', + 'LiteSpeed' + ], + 'cf-cache-status' => [ + 'DYNAMIC', + 'DYNAMIC' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=kcRZemVDEy9D9aUHkha6G5yD1nYt1Ywnqomt7b6%2BizyGuKbFTSNFIuoy9OFOsx1dxNckPna2gQQG%2Fgotmdkrp7jUYS4QWBPqWiEZlJu2OHvzV7NIrHwKlkHkrCWElkLHy04c"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=tV83sdXG3OSii2%2FZi6AEhzZ1Acq3xikxnsbqaEYd0WPLtVdKwloWVpr%2BOSlz%2FFDydoozQ%2FEm2D%2BeBFzq9kRHdsghf8Dkbj1oCRn0fO5LFgFVRn75D4ZMOAy6yquLWQtKtGoh"}],"group":"cf-nel","max_age":604800}' + ], + 'nel' => [ + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload', + 'max-age=31536000; includeSubDomains; preload' + ], + 'server' => [ + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a902c59a53cb1-CDG HTTP/2 200', + '891a902efcd13cb1-CDG' + ], + 'x-powered-by' => [ + 'PHP/5.5.38' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://live.amcharts.com/oembed/?url=https%3A%2F%2Flive.amcharts.com%2FczNjJ%2F&format=json' + ], + 'X-Request-Time' => [ + '0.631 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + +Online Chart Maker | amCharts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +' +]; diff --git a/tests/cache/live.amcharts.com.oembed.fb81481a8420ecbebfc8032d219ae9e6.php b/tests/cache/live.amcharts.com.oembed.fb81481a8420ecbebfc8032d219ae9e6.php new file mode 100644 index 00000000..20e7a5b4 --- /dev/null +++ b/tests/cache/live.amcharts.com.oembed.fb81481a8420ecbebfc8032d219ae9e6.php @@ -0,0 +1,61 @@ + [ + 'date' => [ + 'Sun, 04 Apr 2021 15:22:28 GMT' + ], + 'content-type' => [ + 'application/json' + ], + 'set-cookie' => [ + '__cfduid=d85e8abe03b08352a2608c98d6a8a9a8b1617549747; expires=Tue, 04-May-21 15:22:27 GMT; path=/; domain=.amcharts.com; HttpOnly; SameSite=Lax' + ], + 'x-powered-by' => [ + 'PHP/5.5.38' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-turbo-charged-by' => [ + 'LiteSpeed' + ], + 'cf-cache-status' => [ + 'DYNAMIC' + ], + 'cf-request-id' => [ + '093f137eeb0000d66da59fb000000001' + ], + 'expect-ct' => [ + 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"' + ], + 'report-to' => [ + '{"max_age":604800,"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=g2SMA9QypQzl0%2BsQvkGP5EmtgDuXckFofimMboo%2FlnU4jI8GJhZpLNwXNGOCZguavu8Gx0KyGQL6vRIAPz1l%2Bi0uVRO%2FWI5SgvRih9tQStmPFw%3D%3D"}],"group":"cf-nel"}' + ], + 'nel' => [ + '{"report_to":"cf-nel","max_age":604800}' + ], + 'server' => [ + 'cloudflare' + ], + 'cf-ray' => [ + '63ab8844a810d66d-MAD' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://live.amcharts.com/oembed/?url=%2F%2Flive.amcharts.com%2FczNjJ%2F&format=json' + ], + 'X-Request-Time' => [ + '0.480 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"rich","html":"","iframe_url":"https://open.spotify.com/embed/album/7s66wU1XJ2NsUuWM2NKiUV?utm_source=oembed","width":456,"height":352,"version":"1.0","provider_name":"Spotify","provider_url":"https://spotify.com/","type":"rich","title":"A Cantar con Xabarin (Vol. I e II)","thumbnail_url":"https://i.scdn.co/image/ab67616d00001e022dd9ff41aad54c1d93d50aa6","thumbnail_width":300,"thumbnail_height":300}' +]; diff --git a/tests/cache/open.spotify.com.oembed.ef6aab8b5691cc9b9da2dc988f19e9e2.php b/tests/cache/open.spotify.com.oembed.ef6aab8b5691cc9b9da2dc988f19e9e2.php new file mode 100644 index 00000000..f69e8adf --- /dev/null +++ b/tests/cache/open.spotify.com.oembed.ef6aab8b5691cc9b9da2dc988f19e9e2.php @@ -0,0 +1,73 @@ + [ + 'date' => [ + 'Sat, 09 Oct 2021 00:05:39 GMT', + 'Sat, 09 Oct 2021 00:05:39 GMT' + ], + 'content-type' => [ + 'text/html', + 'application/json; charset=utf-8' + ], + 'location' => [ + 'https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Falbum%2F7s66wU1XJ2NsUuWM2NKiUV&format=json' + ], + 'x-join-the-band' => [ + 'https://www.spotify.com/jobs/', + 'https://www.spotify.com/jobs/' + ], + 'sp-trace-id' => [ + 'ae7fcbf65d5d32ea', + '2e93a1393f853e6d' + ], + 'strict-transport-security' => [ + 'max-age=31536000', + 'max-age=31536000' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'content-encoding' => [ + 'gzip', + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding', + 'Accept-Encoding,Accept-Encoding' + ], + 'server' => [ + 'envoy', + 'envoy' + ], + 'via' => [ + 'HTTP/2 edgeproxy, 1.1 google', + 'HTTP/2 edgeproxy, 1.1 google' + ], + 'alt-svc' => [ + 'clear HTTP/2 200', + 'clear' + ], + 'spotify-request-id' => [ + '3b567c15-4dec-445f-9b0d-5cba748f5f58' + ], + 'set-cookie' => [ + 'sp_t=e9883fac927b45f20ee37e64c7d823e7; path=/; expires=Sun, 09 Oct 2022 00:05:39 GMT; domain=.spotify.com; samesite=none; secure', + 'sp_landing=https%3A%2F%2Fopen.spotify.com%2Foembed; path=/; expires=Sun, 10 Oct 2021 00:05:39 GMT; domain=.spotify.com; samesite=none; secure; httponly' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'Content-Location' => [ + 'https://open.spotify.com/oembed?url=https%3A%2F%2Fopen.spotify.com%2Falbum%2F7s66wU1XJ2NsUuWM2NKiUV&format=json' + ], + 'X-Request-Time' => [ + '0.140 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"html":"","width":456,"height":380,"version":"1.0","provider_name":"Spotify","provider_url":"https://spotify.com/","type":"rich","title":"A Cantar con Xabarin (Vol. I & II)","thumbnail_url":"https://i.scdn.co/image/ab67616d00001e02022aca057f08a1d40c1f0733","thumbnail_width":300,"thumbnail_height":300}' +]; diff --git a/tests/cache/output.jsbin.com.vonesu-10.php b/tests/cache/output.jsbin.com.vonesu-10.php new file mode 100644 index 00000000..44fd67af --- /dev/null +++ b/tests/cache/output.jsbin.com.vonesu-10.php @@ -0,0 +1,213 @@ + [ + 'server' => [ + 'nginx' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:48 GMT' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'set-cookie' => [ + 'jsbin=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT', + 'session=eyJ2ZXJzaW9uIjoiNC4xLjgiLCJjc3JmU2VjcmV0IjoiVl9QZ2RRaWpsdjlTMGpZVnpxQ3pfb2Q3In0=; path=/; expires=Tue, 10 Jun 2025 15:58:48 GMT; domain=.jsbin.com; httponly', + 'session.sig=CaCQoRW37AtKxW14tdzpivhIo0I; path=/; expires=Tue, 10 Jun 2025 15:58:48 GMT; domain=.jsbin.com; httponly' + ], + 'x-robots-tag' => [ + 'nofollow' + ], + 'x-bin-id' => [ + '28610872' + ], + 'x-bin-url' => [ + 'vonesu' + ], + 'x-bin-revision' => [ + '10' + ], + 'etag' => [ + 'W/"f55-IojPR6L49U28VB5rAET2G34sKd8"' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-route' => [ + 'node' + ], + 'Content-Location' => [ + 'http://output.jsbin.com/vonesu/10' + ], + 'X-Request-Time' => [ + '0.216 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + JS Bin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Results when focusing search field
BrowserScreen readerOSResult
Chrome 51VoiceOverMac OS 10.11Reads ”ellipse, insert at start of text, Search label, text”
Firefox 47VoiceOverMac OS 10.11Reads ”Search label, text”
Safari 9VoiceOverMac OS 10.11Reads ”ellipse, Search label, search text field”
IE10NVDA 2015.3Windows 8Reads ”Search label, edit, blank”
Chrome 46NVDA 2015.3Windows 8Reads ”Search label, edit, blank”
Firefox 41NVDA 2015.3Windows 8Reads ”Search label, editable, autocomplete, blank”
IE10JAWS 13Windows 8Reads ”Search label, edit, type in text”
Opera 36JAWS 13Windows 8Reads ”Search label, edit, ellipsis, ellipsis”
IE9JAWS 15Windows 7Reads ”Search label, edit, type in text”
IE9Window-Eyes 9.4Windows 7Reads ”Search label, edit”
+ +

Comment: Chrome and Safari (Mac) seem to be the only browsers that read placeholder text, so far. Safari seems to still read the placeholder text even when there is another value inside the text field.

+ + + + + +' +]; diff --git a/tests/cache/pachunka.deviantart.com.art-cope-145564099.php b/tests/cache/pachunka.deviantart.com.art-cope-145564099.php new file mode 100644 index 00000000..7ee33e81 --- /dev/null +++ b/tests/cache/pachunka.deviantart.com.art-cope-145564099.php @@ -0,0 +1,137 @@ + [ + 'server' => [ + 'CloudFront', + 'Apache' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:45 GMT', + 'Mon, 10 Jun 2024 15:58:45 GMT', + 'Mon, 10 Jun 2024 15:58:46 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=ISO-8859-1', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '167', + '0' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://pachunka.deviantart.com/art/Cope-145564099', + 'https://www.deviantart.com/pachunka/art/Cope-145564099' + ], + 'x-cache' => [ + 'Redirect from cloudfront', + 'Miss from cloudfront', + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 46b7282ebe1a484df942bd68bfa2c656.cloudfront.net (CloudFront)', + '1.1 881a5a546bfcb1f1b6d589576d5ee9f6.cloudfront.net (CloudFront)', + '1.1 98a649570d251d2758f5b0b084e2a774.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD53-P3', + 'MAD53-P3', + 'MAD53-P3' + ], + 'x-amz-cf-id' => [ + 'dYBqZ-3_FS1Q1731PDRQ5F5JED4jhjWMRgqConIjMG2TlBz2GV17yw== HTTP/2 301', + 'SfCoFK2ECsFR87vCIlsOaFTNPFzWc_jvv4uuk8OOaQsq4kSl8jHmDg== HTTP/2 200', + 'BA88aWfJrBEKXzwLu2gIkErMmjUBBtEMM7pRLuy8-_ai8aqQcffRSA==' + ], + 'x-backend' => [ + 'web_http_back', + 'da_deviation_back' + ], + 'cross-origin-opener-policy' => [ + 'same-origin-allow-popups' + ], + 'origin-agent-cluster' => [ + '?1' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'strict-transport-security' => [ + 'max-age=5184000; includeSubDomains' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-dns-prefetch-control' => [ + 'off' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'x-xss-protection' => [ + '0' + ], + 'content-security-policy' => [ + 'object-src wixmp-ed30a86b8c4ca887773594c2.wixmp.com wixmp-395331243bc2089e8c09c8d3.wixmp.com img-deviantart.wixmp.com;script-src \'nonce-b14826d2315ca8f8c7914e0954bb313a\' \'unsafe-inline\' \'unsafe-eval\' \'strict-dynamic\' https: http: ;base-uri \'none\';frame-ancestors \'self\' sta.sh;upgrade-insecure-requests;block-all-mixed-content' + ], + 'accept-ch' => [ + 'Sec-CH-Viewport-Width, Sec-CH-Viewport-Height' + ], + 'accept-ch-lifetime' => [ + '86400' + ], + 'content-language' => [ + 'en' + ], + 'cache-control' => [ + 'no-cache' + ], + 'da-sr' => [ + 'u' + ], + 'server-timing' => [ + 'p;dur=103.6808369755745, r;dur=15.50857099890709, o;dur=9.673744022846222, t;dur=128.8631519973278' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'br' + ], + 'x-seen-by' => [ + '' + ], + 'Content-Location' => [ + 'https://www.deviantart.com/pachunka/art/Cope-145564099' + ], + 'X-Request-Time' => [ + '1.353 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Cope by pachunka on DeviantArt
pachunka on DeviantArthttps://www.deviantart.com/pachunka/art/Cope-145564099pachunka

Deviation Actions

randomduck-2012's avatar

Cope

Published:
3.3K Views

Description

$randomduck for president, 2012.

:iconrandomduck-2012:

There may or may not be some irony surrounding this image.
Image size
448x672px 161.23 KB
© 2009 - 2024 pachunka
Comments5
Join the community to add your comment. Already a deviant? Log In
mhalpert's avatar
I don\'t know why I always think Sasha look like Napoleon when I see this picture. Maybe if his hand was in his shirt?
' +]; diff --git a/tests/cache/pastebin.com.d4biutrm.php b/tests/cache/pastebin.com.d4biutrm.php new file mode 100644 index 00000000..b9c016e2 --- /dev/null +++ b/tests/cache/pastebin.com.d4biutrm.php @@ -0,0 +1,516 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:51 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'x-frame-options' => [ + 'DENY' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '1;mode=block' + ], + 'set-cookie' => [ + '_csrf-frontend=2433125ad79b5109a6ad2c413905810af4eba2abcb8e0167826438b8c2333d4da%3A2%3A%7Bi%3A0%3Bs%3A14%3A%22_csrf-frontend%22%3Bi%3A1%3Bs%3A32%3A%22wVd_L-2EqkMrw0ejMMCuULiY6YJ71SK9%22%3B%7D; path=/; HttpOnly' + ], + 'content-encoding' => [ + 'gzip' + ], + 'cf-cache-status' => [ + 'DYNAMIC' + ], + 'server' => [ + 'cloudflare' + ], + 'cf-ray' => [ + '891a90afe8dd384d-MAD' + ], + 'Content-Location' => [ + 'https://pastebin.com/d4biUtRm' + ], + 'X-Request-Time' => [ + '0.280 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + Pushing new git submodule to Heroku - Pastebin.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+ +
+ + + + + + paste + + + + + +
+ +
+ +
+ + +
+ +
+ +
+
+ +
+ + +
+
+ + + + +
+
Advertisement
+
+
+ + + + + + +
+ +
+ + +
+ +
+ wecsam
+
+
+ + + +

Pushing new git submodule to Heroku

+
+
+ +
+ wecsam +
+ + + + +
+ Jul 5th, 2013 + +
+ +
+ 235
+ +
+ 0
+ +
+ Never
+ +
+ + + Add comment +
+
+
+
+ + + +
+
+
+ Not a member of Pastebin yet? + Sign Up, + it unlocks many cool features!
+
+
+ + +
+
+
+ Bash 1.36 KB + + | None + + | + 0 0
+ +
+ + raw + download + clone + embed + print + + report + + +
+
+
+
  1. $ git push heroku
  2. +
  3. Counting objects: 32, done.
  4. +
  5. Delta compression using up to 2 threads.
  6. +
  7. Compressing objects: 100% (21/21), done.
  8. +
  9. Writing objects: 100% (26/26), 25.15 KiB, done.
  10. +
  11. Total 26 (delta 7), reused 0 (delta 0)
  12. +
  13.  
  14. +
  15. -----> Git submodules detected, installing
  16. +
  17.        Submodule \'lib/Gettext\' (https://github.com/oscarotero/Gettext) registered for path \'lib/Gettext\'
  18. +
  19.        Submodule \'sdk\' (https://github.com/facebook/facebook-php-sdk.git) registered for path \'sdk\'
  20. +
  21.        warning: templates not found /app/vendor/share/git-core/templates
  22. +
  23.        Initialized empty Git repository in /tmp/build_3qsptm4y0jv8u/lib/Gettext/.git/
  24. +
  25.        Submodule path \'lib/Gettext\': checked out \'6dada5d2293633509d01325dbd069bf8b38b7d3b\'
  26. +
  27.        warning: templates not found /app/vendor/share/git-core/templates
  28. +
  29.        Initialized empty Git repository in /tmp/build_3qsptm4y0jv8u/sdk/.git/
  30. +
  31.        Submodule path \'sdk\': checked out \'98f2be163c96a51166354e467b95dd38aa4b0a19\'
  32. +
  33. -----> PHP app detected
  34. +
  35. -----> Bundling Apache version 2.2.22
  36. +
  37. -----> Bundling PHP version 5.3.10
  38. +
  39. -----> Discovering process types
  40. +
  41.        Procfile declares types -> (none)
  42. +
  43.        Default types for PHP   -> web
  44. +
  45.  
  46. +
  47. -----> Compiled slug size: 9.7MB
  48. +
  49. -----> Launching... done, v7
  50. +
  51.        http://project-drillwriter.herokuapp.com deployed to Heroku
  52. +
  53.  
  54. +
  55. To git@heroku.com:project-drillwriter.git
  56. +
  57.    e734d16..f3c4a09  master -> master
  58. +
+
+ + + + + +
+
Advertisement
+
+
+ + + +
+ + + +
+
+ Add Comment
+ +
+
+ Please, Sign In to add comment
+
+
+ +
+ +
+ + + +
+
Advertisement
+
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/play.cadenaser.com.audio-001rd010000004275766.php b/tests/cache/play.cadenaser.com.audio-001rd010000004275766.php new file mode 100644 index 00000000..ebd5ec22 --- /dev/null +++ b/tests/cache/play.cadenaser.com.audio-001rd010000004275766.php @@ -0,0 +1,386 @@ + [ + 'age' => [ + '0' + ], + 'content-encoding' => [ + 'gzip', + 'gzip' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:11 GMT', + 'Mon, 10 Jun 2024 15:59:11 GMT' + ], + 'location' => [ + 'https://cadenaser.com/audio/001RD010000004275766/' + ], + 'server' => [ + 'nginx/1.14.2', + 'openresty' + ], + 'via' => [ + '1.1 varnish-v4' + ], + 'x-cache' => [ + 'MISS' + ], + 'x-varnish' => [ + '47165450' + ], + 'content-length' => [ + '138', + '63020' + ], + 'connection' => [ + 'keep-alive HTTP/2 200' + ], + 'etag' => [ + 'W/"5ecd3-7pgI9sKw3Vw5Jfy7HrBHm5RxQbs"' + ], + 'last-modified' => [ + 'Mon, 10 Jun 2024 15:57:50 GMT' + ], + 'x-arc-pb-request-id' => [ + 'f49e89d8-37ff-4569-8e59-49939b25a860' + ], + 'x-amz-cf-pop' => [ + 'FRA60-P4' + ], + 'x-amz-cf-id' => [ + '5S5N-zQ0KQ-DuF4Rt9HhKob6uzW9rNbEah500mjvZRfKz627alWaLw==' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'cache-control' => [ + 'private, max-age=60' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:00:11 GMT' + ], + 'set-cookie' => [ + 'arc-geo={"georegion":"200","countrycode":"ES","regioncode":"MD","timezone":"GMT+1","continent":"EU"}; expires=Mon, 10-Jun-2024 16:14:11 GMT; path=/' + ], + 'content-security-policy' => [ + 'upgrade-insecure-requests' + ], + 'x-arc-request-id' => [ + '0.4dd191d4.1718035151.290ab598' + ], + 'akamai-true-ttl' => [ + '900' + ], + 'Content-Location' => [ + 'https://cadenaser.com/audio/001RD010000004275766/' + ], + 'X-Request-Time' => [ + '0.243 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Debate electoral gallego, en 'Hoy por Hoy' | Cadena Ser
  1. Podcast
  2. Actualidad

Debate electoral gallego, en 'Hoy por Hoy'

16/09/2016

Debate electoral gallego, en 'Hoy por Hoy'

50:15

Compartir

El código iframe se ha copiado en el portapapeles

<iframe src="https://cadenaser.com/embed/audio/460/001RD010000004275766/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

Ana Pontón, candidata del BNG; Xoaquín Fernández Leiceaga, candidato del PSdG-PSOE; Luis Villares, candidato de En Marea, y Pedro Puy, candidato del PP por A Coruña y coordinador del programa electoral de Alberto Núñez Feijoo debaten en Hoy por Hoy

¿Me lo dices o te lo cuento?

Hay una compañera del equipo que tiene un serio problema con su hija. La niña no para de repetir un...

10/06/2024 | 07:03

Compartir

El código iframe se ha copiado en el portapapeles

<iframe src="https://cadenaser.com/embed/audio/460/1718015960957/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

Episodios anteriores

  • Unos buenos zapatos levantan un traje

    El mitos 2.0 se vistió hoy por los pies. Nuestra colaboradora, la jurista Mariola Urrea, planteó el...

    10/06/2024 | 31:18

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718013824076/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • La pirámide del fin del mundo

    Contamos historias alrededor de lo que construimos, alrededor de las ciudades, los pueblos, las casas...

    10/06/2024 | 08:56

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718011689402/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • Borja Bauzá, autor de "La tribu vertical": "Algunos presidentes de fútbol en los ochenta admitieron y fomentaron a grupos ultras en sus estadios"

    Esta mañana en 'La Dupla', Borja Bauzá, autor del libro "La tribu vertical", nos ha contado cómo se...

    10/06/2024 | 15:48

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718013787041/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • Virtudes que también son defectos

    Empezando por la sinceridad, cuyo exceso la convierte de virtud en defecto, Bob hace una lista de características...

    10/06/2024 | 21:04

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718017667044/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • Europa se derechiza y la extrema derecha sacude el tablero

    Europa se derechiza y la extrema derecha sacude el tablero con sus +victorias en Francia, en Italia...

    10/06/2024 | 02:39:30

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718010702058/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • El nuevo europarlamento, la Europa ultra y divergencia por desinformación

    Con Mariola Urrea, Antón Losada, Víctor Lapuente y José Miguel Contreras. Análisis de los resultados...

    10/06/2024 | 01:07:41

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718008086034/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • Europa vive un auge de la extrema derecha

    Los ultras han ganado en Francia, Italia, Hungría y Austria, mientras que son segunda fuerza en Alemania....

    10/06/2024 | 16:54

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1718001054314/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • Apaguemos de una vez los focos electorales | La firma de Àngels Barceló

    El auge de la ultraderecha sacude las políticas nacionales en dos de los grandes motores de Europa,...

    10/06/2024 | 03:00

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1717998952991/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

  • El avance de la ultraderecha en Europa y sus posibles efectos económicos

    El análisis de actualidad económica, todas las mañanas a las 07:30 con Javier Ruiz, jefe de Economía...

    10/06/2024 | 04:54

    Compartir

    El código iframe se ha copiado en el portapapeles

    <iframe src="https://cadenaser.com/embed/audio/460/1717998672385/" width="100%" height="360" frameborder="0" allowfullscreen></iframe>

Hoy por HoyVer más episodios

Seguir

Hoy por Hoy

© Sociedad Española de Radiodifusión, S.L.U. 2024. Todos los derechos reservados
Sociedad Española de Radiodifusión, S.L.U. realiza una reserva expresa de las reproducciones y usos de los programas radiofónicos, las obras y otras prestaciones accesibles desde este sitio web a medios de lectura mecánica u otros medios que resulten adecuados a tal fin de conformidad con el artículo 67.3 del Real Decreto-ley 24/2021, de 2 de noviembre.

 
  • Cadena SER

  •  
Programación
Cadena SER

Hoy por Hoy

Àngels Barceló

Comparte

Compartir desde el minuto: 00:00
' +]; diff --git a/tests/cache/play.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php b/tests/cache/play.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php new file mode 100644 index 00000000..c9880092 --- /dev/null +++ b/tests/cache/play.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php @@ -0,0 +1,128 @@ + [ + 'location' => [ + 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV' + ], + 'strict-transport-security' => [ + 'max-age=31536000', + 'max-age=31536000' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:20:47 GMT', + 'Sun, 04 Apr 2021 15:20:48 GMT' + ], + 'server' => [ + 'envoy', + 'envoy' + ], + 'content-length' => [ + '0' + ], + 'via' => [ + 'HTTP/2 edgeproxy, 1.1 google', + 'HTTP/2 edgeproxy, 1.1 google' + ], + 'alt-svc' => [ + 'clear HTTP/2 200', + 'clear' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'spotify-request-id' => [ + 'f99758fb-3538-4daf-aab0-b1e79f6164b3' + ], + 'set-cookie' => [ + 'sp_t=a1a62b9eef0c957a09bac5854eafc011; path=/; expires=Mon, 04 Apr 2022 15:20:48 GMT; domain=.spotify.com; samesite=none; secure', + 'sp_landing=https%3A%2F%2Fopen.spotify.com%2Falbum%2F7s66wU1XJ2NsUuWM2NKiUV; path=/; expires=Mon, 05 Apr 2021 15:20:48 GMT; domain=.spotify.com; samesite=none; secure; httponly' + ], + 'content-security-policy' => [ + 'script-src \'self\' \'unsafe-eval\' blob: open.scdn.co open-review.scdn.co quicksilver.scdn.co www.google-analytics.com www.googletagmanager.com static.ads-twitter.com analytics.twitter.com s.pinimg.com sc-static.net https://www.google.com/recaptcha/ cdn.ravenjs.com connect.facebook.net www.gstatic.com sb.scorecardresearch.com pixel-static.spotify.com s3.amazonaws.com/ki.js/51746/b0R.js turbo.qualaroo.com optimize.google.com cdn.cookielaw.org geolocation.onetrust.com www.googleoptimize.com www.fastly-insights.com \'sha256-WfsTi7oVogdF9vq5d14s2birjvCglqWF842fyHhzoNw=\' \'sha256-KRzjHxCdT8icNaDOqPBdY0AlKiIh5F8r4bnbe1PQwss=\'; frame-ancestors \'self\';' + ], + 'x-spotify-open-index' => [ + 'true' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV' + ], + 'X-Request-Time' => [ + '0.571 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + A Cantar con Xabarin (Vol. I & II) - Compilation by Various Artists | Spotify + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +' +]; diff --git a/tests/cache/polldaddy.com.poll-7012505.php b/tests/cache/polldaddy.com.poll-7012505.php new file mode 100644 index 00000000..c51dc57d --- /dev/null +++ b/tests/cache/polldaddy.com.poll-7012505.php @@ -0,0 +1,1528 @@ + [ + 'server' => [ + 'nginx', + 'nginx', + 'nginx' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:52 GMT', + 'Mon, 10 Jun 2024 15:58:52 GMT', + 'Mon, 10 Jun 2024 15:58:53 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '162' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://polldaddy.com/poll/7012505/%20%20HTTP/2%20301', + 'https://poll.fm/7012505' + ], + 'alt-svc' => [ + 'h3=":443"; ma=86400 HTTP/2 200', + 'h3=":443"; ma=86400' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-language' => [ + 'en' + ], + 'set-cookie' => [ + 'PD_REQ_AUTH=e3141d36479a149dfe610c601032d9c5; path=/; domain=.poll.fm; secure; SameSite=None; expires=Mon, 10 Jun 2024 16:03:53 GMT;HttpOnly' + ], + 'content-encoding' => [ + 'br' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'Content-Location' => [ + 'https://poll.fm/7012505' + ], + 'X-Request-Time' => [ + '1.666 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + Which design do you prefer? (poll 7012505) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +

Which design do you prefer?

+
+
+
+
+ +
+ +
+ +
+
+ Option image +
+
+
+ + + + + +
+
+
+ +
+
+ Option image +
+
+
+ + + + + +
+
+
+
+ + +
+
+ + Vote + View Results +
+ +
+ +
+
+ + +
+ + +
+
27 Comments
+

+
    + +
  • + + \'\'
    +
    + + Tecia Beulens + + - 11 years ago + + +

    +
    +

    Option 1 pls. Looks more organized. :)

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Rivcah + + - 11 years ago + + +

    +
    +

    -

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Lisa + + - 11 years ago + + +

    +
    +

    I like option 1 better as I really like the little bit of info. I much prefer the 3 across than the 2 across. I know it probably doesn\'t matter in the grand scheme of things, but I would rather see all pictures be a uniform size so that they all lined up evenly. It is probably just me, but I like things neat and tidy with a set structure. Thanks for asking for our input Chris!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Michelle + + - 11 years ago + + +

    +
    +

    They both load the exact same on my iPad so I don\'t see a difference. BUT I love that u finally made the auctions 3 wide used to take me forever to scroll down and wait for items to load. I\'d highly suggest having sections for ur own auctions, ended, sold, current so it\'s easier to find if your someone like ME who has LOTS TO SELL haha thanks.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + B + + - 11 years ago + + +

    +
    +

    #1 takes up too much room. I love #2. Takes up less space so we can see more of the auctions in one go. If i\'m REALLY interested in something I dont mind clicking the picture to see but for me to see ALL the info on EVERY SINGLE item posted is over kill. 97% of the items listed I am not interested in and i\'m sure that goes for most users. If we can see the info we want on the items we want that\'s the way to go. #2!!!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Barb + + - 11 years ago + + +

    +
    +

    First let me say thank you to those who commented above or I would have had absolutely no idea what the differences were to be looking for.

    +

    Secondly, after looking at them both each five times I still have a difficult time seeing the huge difference between the two options. I may need more clarification in a written form if that is possible before I would vote.

    +

    I appreciate all the upgrades that are being done and thank you again to the admins for the tireless work you have all done!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + angela + + - 11 years ago + + +

    +
    +

    number 1. i need the tiny bit of info so I know if its something I\'m interested in or not. I don\'t bother to click on photos that dont have any info.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Jodie + + - 11 years ago + + +

    +
    +

    I like # 2 then u can open the item if u like it and skip all the unnecessary info and see more items at a time.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Tanya + + - 11 years ago + + +

    +
    +

    I like the look of option 2, personally, but I prefer seeing the little tid bit of info in option 1.
    +Option 2 looks cleaner/sleeker, but option 1 means I don\'t have to click on every item of clothing I like and look for a size (for example)

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Tanyaut + + - 11 years ago + + +

    +
    +

    I like the look of option 2, personally, but I prefer seeing the little tid bit of info in option 1.
    +Option 2 looks cleaner/sleeker, but option 1 means I don\'t have to click on every item of clothing I like and look for a size (for example)

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Gail + + - 11 years ago + + +

    +
    +

    Option #1. More information saves a lot of time looking at items that aren\'t your size etc... Thanks!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Michelle\'s Sew Biz - Michelle + + - 11 years ago + + +

    +
    +

    we need to clarify on postings what part of Maple Ridge- and if in your wisdom you can make the selection stick to the user just clicks East Maple Ridge, WEst etc.........folks wont come from PM to EMR so they get annoyed when they find out. Our geo area is so large.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Uniq Boutiq + + - 11 years ago + + +

    +
    +

    Hi Admins! We definitely need to have info on the post. Brand/name of item, size, price, sellers name (in case we do/do not want to buy form them) etc. More info on the visible post is important. People do not want to have to click on every single item just to get the scoop. It takes waaay to long, and will be a deterrent for new members and old... :) Please do option 1, as option 2 is not good.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Kelly keno + + - 11 years ago + + +

    +
    +

    I really like #2 but only if the sellers name and rating is visible.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Kelly keno + + - 11 years ago + + +

    +
    +

    I really like #2 but only if the sellers name and rating is visible.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Kelly keno + + - 11 years ago + + +

    +
    +

    I really like #2 but only if the sellers name and rating is visible.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Danika + + - 11 years ago + + +

    +
    +

    Number 1

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Danika + + - 11 years ago + + +

    +
    +

    Number 1

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Danika + + - 11 years ago + + +

    +
    +

    Number 1

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Danika + + - 11 years ago + + +

    +
    +

    Number 1

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Adrianna + + - 11 years ago + + +

    +
    +

    It would be Great if there was a photo album option like the "old" version because then people can look at albums for things they like versus scrolling endlessly...just an idea!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Sofie + + - 11 years ago + + +

    +
    +

    I prefer the first option because it gives some of the details of the auction. For instance, if there\'s a pair of shoes I like, but see on the front page they are not my size, I can quickly pass over them. Without the detail that we have now, I\'ll end up clicking on a bunch of items that don\'t fit my needs.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Kelsey + + - 11 years ago + + +

    +
    +

    I agree #2. You can click the item to get more info if interested. Love the new site!!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Casey Bell + + - 11 years ago + + +

    +
    +

    Catherine - if you click on the photo - it makes it full size.

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Tasha + + - 11 years ago + + +

    +
    +

    voted for #1 bit wanted #2. #2 is much better

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Catherine + + - 11 years ago + + +

    +
    +

    it would help if the picture was bigger so we could see the differences to make a better informed decision!

    +
    +

    +
  • + +
  • + + \'\'
    +
    + + Richard + + - 11 years ago + + +

    +
    +

    I really like option 2!

    +
    +

    +
  • +
+

+

+ +
+
Leave a Comment
+ +
+ + + + + + + + + + + + + + + + + + + + + +

0/4000 chars

+
+ Submit Comment +
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+ + + + + +
+ + +
+ + + +
+ + + +' +]; diff --git a/tests/cache/public-api.wordpress.com.oembed.86119ca8bab033b76d134257636de440.php b/tests/cache/public-api.wordpress.com.oembed.86119ca8bab033b76d134257636de440.php new file mode 100644 index 00000000..ab57f3bc --- /dev/null +++ b/tests/cache/public-api.wordpress.com.oembed.86119ca8bab033b76d134257636de440.php @@ -0,0 +1,47 @@ + [ + 'server' => [ + 'nginx' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:22 GMT' + ], + 'content-type' => [ + 'application/json; charset=UTF-8' + ], + 'vary' => [ + 'Accept-Encoding', + 'accept, content-type' + ], + 'x-hacker' => [ + 'Want root? Visit join.a8c.com/hacker and mention this header.' + ], + 'host-header' => [ + 'WordPress.com' + ], + 'content-encoding' => [ + 'br' + ], + 'x-ac' => [ + '2.mad _dca BYPASS' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'alt-svc' => [ + 'h3=":443"; ma=86400' + ], + 'Content-Location' => [ + 'https://public-api.wordpress.com/oembed/?format=json&url=https%3A%2F%2Fwordpress.tv%2F2013%2F09%2F06%2Fdave-ross-optimize-image-files-like-a-pro%2F&for=wpcom-auto-discovery' + ], + 'X-Request-Time' => [ + '0.340 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","provider_name":"WordPress.tv","provider_url":"http:\\/\\/wordpress.tv","author_name":"WordPress.tv","author_url":"https:\\/\\/wordpress.tv\\/author\\/anonvideoupload\\/","title":"Dave Ross: Optimize Image Files Like a Pro","html":"
Dave Ross: Optimize Image Files Like a Pro<\\/a><\\/blockquote>
+
+
+

Play by Play

+
+
+

Most CSS3 properties 

+ +

are supported within SVG.

+ +

 

+ +

The Exception?

+ +

3D Transforms.  

+ +

 

+ +

Boo.. :-(

+
+
+
+
http://bit.ly/play-by-play
+
+

Issues &

+ +

G  tchas

+
+
+

CSS Pre-processors

+
+
+

Say goodbye to Sass, Less, Stylus, etc ... 

+
+
+

Say hello to CSS prefixes again

+
+ +
+
+

  Upload Support can be... patchy

+
+ + +
+
+
+
+

Image hosting services: Flickr, Imgur, etc 

+
+
+

CMSs like Wordpress block SVG upload

+
+
+

Github is a free, reliable hosting option

+
+
+

Tools &
+Helpers

+
+

Use Code Playgrounds

+
+
+
    +
  • Codepen.io
  • +
  • CSSDeck.com
  • +
  • Dabblet.com
  • +
+
+
+

.. all render SVG as you write/paste it

+
+
+

  (WARNING: Never re-open your hand-edited SVG in your Illustrator/Inkscape!)

+
+
+
+
+
+
    +
  • petercollingridge.appspot.com/svg-editor
  • +
+
+
+

SVG Optimizers

+
+
+

Useful SVG

+ +

Resources

+
+

WikiMedia Commons

+
+
+

World/country maps:     http://commons.wikimedia.org/

+
+
+

Open Street Maps

+
+
+

http://www.openstreetmap.org/

+
+
+

Plot.ly

+
+
+

SVG graphs    https://plot.ly/

+
+
+

Thanks for listening!

+
+
+
+

Photo credits

+
+
+

Alex Walker

+ +

@alexmwalker

+
+
+

Slides: https://slides.com/alexwalker/responsive-svg/ 

+
+
+

Demos: http://codepen.io/alexmwalker/public/

+
+
+ +
+ +
+ + + + +
+
+
+

responsive-svg

+

By Alex Walker

+
+
+ +
+
+
+

+

+
+
+ + + + +
+
+
+ + +
+ + +
+
+ +
+ +
+ +
+ +
+
+

responsive-svg

+
    +
  • + + +
  • +
  • + + +
  • +
  • + + 11,914 +
  • +
+
+ + + +
+
+
+ + + +
+ + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/snipplr.com.view-72914-better-html-5-basic-starter-template.php b/tests/cache/snipplr.com.view-72914-better-html-5-basic-starter-template.php new file mode 100644 index 00000000..6610a617 --- /dev/null +++ b/tests/cache/snipplr.com.view-72914-better-html-5-basic-starter-template.php @@ -0,0 +1,422 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:05 GMT', + 'Mon, 10 Jun 2024 15:59:06 GMT', + 'Mon, 10 Jun 2024 15:59:06 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=UTF-8', + 'text/html; charset=UTF-8' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://snipplr.com/view/72914/better-html-5-basic-starter-template', + '/login/' + ], + 'cf-cache-status' => [ + 'DYNAMIC', + 'DYNAMIC', + 'DYNAMIC' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=pjUZbEDf5vtXXjXlg3s0fLRsldl8g11G%2FIPn7zlyBdP72R%2B%2FdsfsHmbuaJ%2FwLlo9iuJ6iPqWsyBrxYd9kJKXObgRyBoY4NtH3YT9cDIiAs97MAHTWj5i1sRcO%2FwG"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=gLEQgfs7qbqLNO9hz2%2FNv085Z78p5wuKHOtC06K5gGxIrvhPjtIsoGmm6%2FuCh6feDlq4loCA3saTvTAm%2FigMRjPoGtEvRjtAbbGFBcZpKzYQGo3cjlern1Y3Dbh%2B"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=kvpOpqUBymk0wOsExPH9SnkqpNafr%2B9xqf4c3d8%2FSJ%2Fv3KawMzGsN5lhsg0oLb3KFWLusjRcccTCYffOvZWuMqs047xM4GA3xGAn2TZDTfQCTaowj%2BW8jfjMll13"}],"group":"cf-nel","max_age":604800}' + ], + 'nel' => [ + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' + ], + 'server' => [ + 'cloudflare', + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a910a9b093150-MAD', + '891a910d7daf3c98-CDG HTTP/2 200', + '891a9110ba143c98-CDG' + ], + 'alt-svc' => [ + 'h2=":443"; ma=60 HTTP/2 302' + ], + 'x-powered-by' => [ + 'PHP/7.3.12', + 'PHP/7.3.12' + ], + 'set-cookie' => [ + 'PHPSESSID=to7a0126j2ummn48vka0niqg05; path=/; secure; HttpOnly; SameSite=lax' + ], + 'cache-control' => [ + 'max-age=0, must-revalidate, private', + 'max-age=0, must-revalidate, private' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 15:59:06 GMT', + 'Mon, 10 Jun 2024 15:59:06 GMT' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains; preload', + 'max-age=63072000; includeSubDomains; preload' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://snipplr.com/login/' + ], + 'X-Request-Time' => [ + '1.328 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + +Snipplr - Login + + + + + + + + + + + + +
+
+ +
+
+ +
+
+

Login to Your Account

+
+
+
+
+

+ + +

+

+ + +

+

+ + +

+

+Forgot your password? +

+

Don\'t have an account? Register now!

+
+
+
+
+
+ + + +
+
+
+










+
+
+
+ + + + + + + + + + + +' +]; diff --git a/tests/cache/soundcloud.com.bruceneilmusic.php b/tests/cache/soundcloud.com.bruceneilmusic.php new file mode 100644 index 00000000..f1947b7b --- /dev/null +++ b/tests/cache/soundcloud.com.bruceneilmusic.php @@ -0,0 +1,1017 @@ + [ + 'content-type' => [ + 'text/html' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'x-pants' => [ + 'distant-towel' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'cache-control' => [ + 'private, max-age=0, no-cache, no-store' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'server-timing' => [ + 'experiments; dur=4.820942; desc="api-v2/experiments", enabledFeatures; dur=4.193446; desc="api-v2/enabledFeatures", geoip; dur=1.170337; desc="geoip/geoip", resolve; dur=51.845848; desc="api-v2/resolve", privacySettings; dur=4.956816; desc="api-v2/privacySettings", geoip; dur=1.370773; desc="geoip/geoip", userTracks; dur=91.694115; desc="api-v2/userTracks"' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:21:58 GMT' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubdomains; preload' + ], + 'server' => [ + 'am/2' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 4ebc80fbe8c95fbda707a7dd4b84a6b9.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD51-C1' + ], + 'x-amz-cf-id' => [ + 'wkPM1HgacXLYbEdP03-tmUcBeK5pxtROOn59XVoH2ond0NMWtluGeQ==' + ], + 'Content-Location' => [ + 'https://soundcloud.com/bruceneilmusic' + ], + 'X-Request-Time' => [ + '0.261 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + +Bruce Neil | Free Listening on SoundCloud + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+

+Your current browser isn\'t compatible with SoundCloud.
+Please download one of our supported browsers. Need help? +

+ +
+ +
+

Sorry! Something went wrong

+
+

Is your network connection unstable or browser outdated?

+
+ +
+ +

+Popular searches +

+
+ + + + + + + + + + + +' +]; diff --git a/tests/cache/soundcloud.com.ididthat-1-lowe-ct-cape-times-world-cup.php b/tests/cache/soundcloud.com.ididthat-1-lowe-ct-cape-times-world-cup.php new file mode 100644 index 00000000..98da6362 --- /dev/null +++ b/tests/cache/soundcloud.com.ididthat-1-lowe-ct-cape-times-world-cup.php @@ -0,0 +1,218 @@ + [ + 'content-type' => [ + 'text/html' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'x-pants' => [ + 'distant-towel' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'cache-control' => [ + 'private, max-age=0, no-cache, no-store' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'server-timing' => [ + 'experiments; dur=6.998703; desc="api-v2/experiments", enabledFeatures; dur=5.115162; desc="api-v2/enabledFeatures", geoip; dur=1.22577; desc="geoip/geoip", resolve; dur=120.524476; desc="api-v2/resolve", privacySettings; dur=7.108097; desc="api-v2/privacySettings", geoip; dur=1.884143; desc="geoip/geoip", user; dur=25.316278; desc="api-v2/user", trackComments; dur=33.581175; desc="api-v2/trackComments"' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:37 GMT' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubdomains; preload' + ], + 'server' => [ + 'am/2' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 c02c12149d44c9deefaab126c94c3d3f.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD51-C1' + ], + 'x-amz-cf-id' => [ + 'JEgublk4lfrKNf40NLGWbPqS7zp2cV3pwWlxi6rrqjsWn_XsCo1oKw==' + ], + 'Content-Location' => [ + 'https://soundcloud.com/ididthat-1/lowe-ct-cape-times-world-cup' + ], + 'X-Request-Time' => [ + '0.275 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + +LOWE CT Cape Times - World Cup by IDIDTHAT.co | IDIDTHAT Co | Free Listening on SoundCloud + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+

+Your current browser isn\'t compatible with SoundCloud.
+Please download one of our supported browsers. Need help? +

+ +
+ +
+

Sorry! Something went wrong

+
+

Is your network connection unstable or browser outdated?

+
+ +
+ +

+Popular searches +

+
+ + + + + + + + + + + +' +]; diff --git a/tests/cache/soundcloud.com.oembed.5de734c4e9599059e35a8b0f012ed0ad.php b/tests/cache/soundcloud.com.oembed.5de734c4e9599059e35a8b0f012ed0ad.php new file mode 100644 index 00000000..7d008269 --- /dev/null +++ b/tests/cache/soundcloud.com.oembed.5de734c4e9599059e35a8b0f012ed0ad.php @@ -0,0 +1,79 @@ + [ + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'status' => [ + '200 OK' + ], + 'access-control-allow-headers' => [ + 'Accept, Authorization, Content-Type, Origin' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'access-control-allow-methods' => [ + 'GET, PUT, POST, DELETE' + ], + 'access-control-expose-headers' => [ + 'Date' + ], + 'x-ua-compatible' => [ + 'IE=Edge,chrome=1' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:38 GMT' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubdomains; preload' + ], + 'server' => [ + 'am/2' + ], + 'content-encoding' => [ + 'gzip' + ], + 'etag' => [ + 'W/"cb62c16cfad142cb9b93823269f4d3e2"' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 c02c12149d44c9deefaab126c94c3d3f.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD51-C1' + ], + 'x-amz-cf-id' => [ + 'CAbmZ-XusAByNbPCymnI2wmhexjH9OFBPSQc71qJhCPEP4YMvw3LHQ==' + ], + 'Content-Location' => [ + 'https://soundcloud.com/oembed?url=https%3A%2F%2Fsoundcloud.com%2Fididthat-1%2Flowe-ct-cape-times-world-cup&format=json' + ], + 'X-Request-Time' => [ + '0.127 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":1.0,"type":"rich","provider_name":"SoundCloud","provider_url":"https://soundcloud.com/","height":400,"width":"100%","title":"LOWE CT Cape Times - World Cup by IDIDTHAT.co","description":"","thumbnail_url":"https://soundcloud.com/images/fb_placeholder.png","html":"","author_name":"IDIDTHAT.co","author_url":"https://soundcloud.com/ididthat-1"}' +]; diff --git a/tests/cache/soundcloud.com.oembed.a0c7770afe60e35821ee2d7c8e963044.php b/tests/cache/soundcloud.com.oembed.a0c7770afe60e35821ee2d7c8e963044.php new file mode 100644 index 00000000..a77dd4d5 --- /dev/null +++ b/tests/cache/soundcloud.com.oembed.a0c7770afe60e35821ee2d7c8e963044.php @@ -0,0 +1,88 @@ + [ + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'status' => [ + '200 OK' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'access-control-expose-headers' => [ + 'Date' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-request-id' => [ + '666722DC25F002FD52C40' + ], + 'access-control-allow-headers' => [ + 'Accept, Authorization, Content-Type, Origin' + ], + 'access-control-allow-methods' => [ + 'GET, PUT, POST, DELETE' + ], + 'x-download-options' => [ + 'noopen' + ], + 'etag' => [ + 'W/"e3785445fa9a03b1bc8c344377534a37"' + ], + 'x-frame-options' => [ + 'SAMEORIGIN, SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:25 GMT' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubdomains; preload' + ], + 'server' => [ + 'am/2' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 6c26d69c095f5a0598b0200e04f7026a.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD56-P3' + ], + 'x-amz-cf-id' => [ + 'F9NtmwxNuWdoXjMALkCEftxjl5VFCP89d0VP0FjtPBZGvISzrFiULg==' + ], + 'Content-Location' => [ + 'https://soundcloud.com/oembed?url=https%3A%2F%2Fsoundcloud.com%2Fzedsdead%2Fzeds-dead-twin-shadow-lost-you-feat-dangelo-lacy&format=json' + ], + 'X-Request-Time' => [ + '0.116 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":1.0,"type":"rich","provider_name":"SoundCloud","provider_url":"https://soundcloud.com/","height":400,"width":"100%","title":"Zeds Dead feat. Twin Shadow & D\'Angelo Lacy - Lost You by Zeds Dead","description":"MUSIC VIDEO : https://www.youtube.com/watch?v=VJm7IPrBmLY\\r\\n\\r\\nZeds Dead\\r\\nwww.facebook.com/zedsdead\\r\\nwww.twitter.com/whoszed\\r\\nwww.instagram.com/zedsdeadofficial\\r\\n\\r\\nTwin Shadow\\r\\nwww.facebook.com/twnshdw\\r\\nwww.twitter.com/twinshadow\\r\\nwww.instagram.com/thetwinshadow\\r\\n\\r\\n","thumbnail_url":"https://i1.sndcdn.com/artworks-fdcKTkNSeA5J-0-t500x500.jpg","html":"","author_name":"Zeds Dead","author_url":"https://soundcloud.com/zedsdead"}' +]; diff --git a/tests/cache/soundcloud.com.oembed.eb2a146ee30ee20c3a1a170f0910037e.php b/tests/cache/soundcloud.com.oembed.eb2a146ee30ee20c3a1a170f0910037e.php new file mode 100644 index 00000000..c58bccb3 --- /dev/null +++ b/tests/cache/soundcloud.com.oembed.eb2a146ee30ee20c3a1a170f0910037e.php @@ -0,0 +1,79 @@ + [ + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'status' => [ + '200 OK' + ], + 'access-control-allow-headers' => [ + 'Accept, Authorization, Content-Type, Origin' + ], + 'cache-control' => [ + 'max-age=0, private, must-revalidate' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'access-control-allow-methods' => [ + 'GET, PUT, POST, DELETE' + ], + 'access-control-expose-headers' => [ + 'Date' + ], + 'x-ua-compatible' => [ + 'IE=Edge,chrome=1' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:21:58 GMT' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubdomains; preload' + ], + 'server' => [ + 'am/2' + ], + 'content-encoding' => [ + 'gzip' + ], + 'etag' => [ + 'W/"67bfde4180ceb866773f62a24342d449"' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 2bfefa9edba21d94426d6e53f8ee4516.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD51-C1' + ], + 'x-amz-cf-id' => [ + 'xiIrS8d9iGlsV2glyKvNC_Pm3cmx7nbT5m7hhnQErBQMBeu1LT8ztA==' + ], + 'Content-Location' => [ + 'https://soundcloud.com/oembed?url=https%3A%2F%2Fsoundcloud.com%2Fbruceneilmusic&format=json' + ], + 'X-Request-Time' => [ + '0.125 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":1.0,"type":"rich","provider_name":"SoundCloud","provider_url":"https://soundcloud.com/","height":450,"width":"100%","title":"Bruce Neil","description":"Bruce Neil from Wokingham is a singer/songwriter with a folk inspired sound, producing songs with heartfelt depth and lyrics that captivate the listener, taking them on an insightful and thought-provoking journey. As a winner of BBC Introducing, resulting in air play nationally, he has recently achieved widespread public attention following the video release of his percussive folk rendition of Guns N’ Roses track Paradise City. Not only did this go viral on social media, it was endorsed by the band themselves and has achieved recognition and air play from several US radio stations. He takes his musical inspiration and guitar-playing style from the likes of Passenger and Mick Flannery.","thumbnail_url":"https://i1.sndcdn.com/avatars-000137863509-h9h7dr-t500x500.jpg","html":"","author_name":"Bruce Neil","author_url":"https://soundcloud.com/bruceneilmusic"}' +]; diff --git a/tests/cache/soundcloud.com.zedsdead-zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy.php b/tests/cache/soundcloud.com.zedsdead-zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy.php new file mode 100644 index 00000000..d67083dd --- /dev/null +++ b/tests/cache/soundcloud.com.zedsdead-zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy.php @@ -0,0 +1,407 @@ + [ + 'content-type' => [ + 'text/html' + ], + 'x-pants' => [ + 'distant-towel' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'cache-control' => [ + 'private, max-age=0, no-cache, no-store' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'server-timing' => [ + 'enabledFeatures; dur=6.496586; desc="api-v2/enabledFeatures", experiments; dur=5.57913; desc="api-v2/experiments", geoip; dur=1.61953; desc="geoip/geoip", resolve; dur=40.613463; desc="api-v2/resolve", privacySettings; dur=5.840876; desc="api-v2/privacySettings", user; dur=9.263024; desc="api-v2/user", trackComments; dur=57.467158; desc="api-v2/trackComments"' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:25 GMT' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubdomains; preload' + ], + 'server' => [ + 'am/2' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 32bc8c16ed82342d55409baf8befba44.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD56-P3' + ], + 'x-amz-cf-id' => [ + '7mOVykfoKCypn9REh5WctNhyZOTjizHXX70Rs1c2w_OEQxhhHheWsw==' + ], + 'Content-Location' => [ + 'https://soundcloud.com/zedsdead/zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy' + ], + 'X-Request-Time' => [ + '0.238 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + +Stream Zeds Dead feat. Twin Shadow & D'Angelo Lacy - Lost You by Zeds Dead | Listen online for free on SoundCloud + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+

+Your current browser isn\'t compatible with SoundCloud.
+Please download one of our supported browsers. +Need help? +

+ +
+ +
+

Sorry! Something went wrong

+
+

Is your network connection unstable or browser outdated?

+
+ +
+ +

+Popular searches +

+
+ + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/t.co.4dk3jc2btt.php b/tests/cache/t.co.4dk3jc2btt.php new file mode 100644 index 00000000..cac8ba28 --- /dev/null +++ b/tests/cache/t.co.4dk3jc2btt.php @@ -0,0 +1,55 @@ + [ + 'cache-control' => [ + 'private,max-age=300' + ], + 'content-encoding' => [ + 'gzip' + ], + 'content-length' => [ + '177' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:00 GMT' + ], + 'expires' => [ + 'Sun, 04 Apr 2021 15:26:59 GMT' + ], + 'server' => [ + 'tsa_f' + ], + 'set-cookie' => [ + 'muc=43ad3941-dd44-41d0-86a0-db40d36da4db; Max-Age=63072000; Expires=Tue, 04 Apr 2023 15:21:59 GMT; Domain=t.co; Secure; SameSite=None' + ], + 'strict-transport-security' => [ + 'max-age=0' + ], + 'vary' => [ + 'Origin' + ], + 'x-connection-hash' => [ + '3df298a187eae57ac3788beb08f622e3' + ], + 'x-response-time' => [ + '111' + ], + 'x-xss-protection' => [ + '0' + ], + 'Content-Location' => [ + 'https://t.co/4DK3Jc2BTt' + ], + 'X-Request-Time' => [ + '0.336 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'https://buff.ly/2uSOHDs' +]; diff --git a/tests/cache/twitter.com.pepephone-status-436461658601713664.php b/tests/cache/twitter.com.pepephone-status-436461658601713664.php new file mode 100644 index 00000000..d62335ac --- /dev/null +++ b/tests/cache/twitter.com.pepephone-status-436461658601713664.php @@ -0,0 +1,148 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:29 GMT', + 'Mon, 10 Jun 2024 15:59:29 GMT' + ], + 'perf' => [ + '7402827104', + '7402827104' + ], + 'vary' => [ + 'Accept' + ], + 'expiry' => [ + 'Tue, 31 Mar 1981 05:00:00 GMT', + 'Tue, 31 Mar 1981 05:00:00 GMT' + ], + 'pragma' => [ + 'no-cache', + 'no-cache' + ], + 'server' => [ + 'tsa_f', + 'tsa_f' + ], + 'location' => [ + 'https://x.com/pepephone/status/436461658601713664' + ], + 'set-cookie' => [ + 'ct0=; Max-Age=-1718035168; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=Lax', + 'ct0=; Max-Age=-1718035168; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Path=/; Domain=.x.com; Secure; SameSite=Lax' + ], + 'content-type' => [ + 'text/plain; charset=utf-8', + 'text/html; charset=utf-8' + ], + 'x-powered-by' => [ + 'Express', + 'Express' + ], + 'cache-control' => [ + 'no-cache, no-store, must-revalidate, pre-check=0, post-check=0', + 'no-store, max-age=0' + ], + 'last-modified' => [ + 'Mon, 10 Jun 2024 15:59:29 GMT', + 'Mon, 10 Jun 2024 15:59:29 GMT' + ], + 'x-frame-options' => [ + 'DENY', + 'DENY' + ], + 'x-transaction-id' => [ + 'd2885edf4c0c88cd', + 'cdb4fbca86634caf' + ], + 'x-xss-protection' => [ + '0', + '0' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'content-security-policy' => [ + 'connect-src \'self\' blob: https://api.x.ai https://api.x.com https://*.pscp.tv https://*.video.pscp.tv https://*.twimg.com https://api.twitter.com https://api.x.com https://api-stream.twitter.com https://api-stream.x.com https://ads-api.twitter.com https://ads-api.x.com https://aa.twitter.com https://aa.x.com https://caps.twitter.com https://caps.x.com https://pay.twitter.com https://pay.x.com https://sentry.io https://ton.twitter.com https://ton.x.com https://ton-staging.atla.twitter.com https://ton-staging.atla.x.com https://ton-staging.pdxa.twitter.com https://ton-staging.pdxa.x.com https://twitter.com https://x.com https://upload.twitter.com https://upload.x.com https://www.google-analytics.com https://accounts.google.com/gsi/status https://accounts.google.com/gsi/log https://checkoutshopper-live.adyen.com wss://*.pscp.tv https://vmap.snappytv.com https://vmapstage.snappytv.com https://vmaprel.snappytv.com https://vmap.grabyo.com https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net https://media.riffsy.com https://*.giphy.com https://media.tenor.com https://c.tenor.com ws://localhost:8008/v2/ipc https://ads-twitter.com https://analytics.twitter.com https://analytics.x.com ; default-src \'self\'; form-action \'self\' https://twitter.com https://*.twitter.com https://x.com https://*.x.com https://localhost.twitter.com:3443 https://localhost.x.com:3443; font-src \'self\' https://*.twimg.com; frame-src \'self\' https://twitter.com https://x.com https://mobile.twitter.com https://mobile.x.com https://pay.twitter.com https://pay.x.com https://cards-frame.twitter.com https://accounts.google.com/ https://client-api.arkoselabs.com/ https://iframe.arkoselabs.com/ https://vaultjs.apideck.com/ https://recaptcha.net/recaptcha/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/; img-src \'self\' blob: data: https://*.cdn.twitter.com https://*.cdn.x.com https://ton.twitter.com https://ton.x.com https://*.twimg.com https://analytics.twitter.com https://analytics.x.com https://cm.g.doubleclick.net https://www.google-analytics.com https://maps.googleapis.com https://www.periscope.tv https://www.pscp.tv https://ads-twitter.com https://ads-api.twitter.com https://ads-api.x.com https://media.riffsy.com https://*.giphy.com https://media.tenor.com https://c.tenor.com https://*.pscp.tv https://*.periscope.tv https://prod-periscope-profile.s3-us-west-2.amazonaws.com https://platform-lookaside.fbsbx.com https://scontent.xx.fbcdn.net https://scontent-sea1-1.xx.fbcdn.net https://*.googleusercontent.com https://t.co/1/i/adsct; manifest-src \'self\'; media-src \'self\' blob: https://twitter.com https://x.com https://*.twimg.com https://*.vine.co https://*.pscp.tv https://*.video.pscp.tv https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net; object-src \'none\'; script-src \'self\' \'unsafe-inline\' https://*.twimg.com https://recaptcha.net/recaptcha/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://client-api.arkoselabs.com/ https://www.google-analytics.com https://twitter.com https://x.com https://accounts.google.com/gsi/client https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js https://www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js https://static.ads-twitter.com \'nonce-MzczYmZhNmUtZjExMS00NTZjLTg0YWQtZGZhYWFlMmZhNGM2\'; style-src \'self\' \'unsafe-inline\' https://accounts.google.com/gsi/style https://*.twimg.com; worker-src \'self\' blob:; report-uri https://twitter.com/i/csp_report?a=O5RXE%3D%3D%3D&ro=false', + 'connect-src \'self\' blob: https://api.x.ai https://api.x.com https://*.pscp.tv https://*.video.pscp.tv https://*.twimg.com https://api.twitter.com https://api.x.com https://api-stream.twitter.com https://api-stream.x.com https://ads-api.twitter.com https://ads-api.x.com https://aa.twitter.com https://aa.x.com https://caps.twitter.com https://caps.x.com https://pay.twitter.com https://pay.x.com https://sentry.io https://ton.twitter.com https://ton.x.com https://ton-staging.atla.twitter.com https://ton-staging.atla.x.com https://ton-staging.pdxa.twitter.com https://ton-staging.pdxa.x.com https://twitter.com https://x.com https://upload.twitter.com https://upload.x.com https://www.google-analytics.com https://accounts.google.com/gsi/status https://accounts.google.com/gsi/log https://checkoutshopper-live.adyen.com wss://*.pscp.tv https://vmap.snappytv.com https://vmapstage.snappytv.com https://vmaprel.snappytv.com https://vmap.grabyo.com https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net https://media.riffsy.com https://*.giphy.com https://media.tenor.com https://c.tenor.com ws://localhost:8008/v2/ipc https://ads-twitter.com https://analytics.twitter.com https://analytics.x.com ; default-src \'self\'; form-action \'self\' https://twitter.com https://*.twitter.com https://x.com https://*.x.com https://localhost.twitter.com:3443 https://localhost.x.com:3443; font-src \'self\' https://*.twimg.com; frame-src \'self\' https://twitter.com https://x.com https://mobile.twitter.com https://mobile.x.com https://pay.twitter.com https://pay.x.com https://cards-frame.twitter.com https://accounts.google.com/ https://client-api.arkoselabs.com/ https://iframe.arkoselabs.com/ https://vaultjs.apideck.com/ https://recaptcha.net/recaptcha/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/; img-src \'self\' blob: data: https://*.cdn.twitter.com https://*.cdn.x.com https://ton.twitter.com https://ton.x.com https://*.twimg.com https://analytics.twitter.com https://analytics.x.com https://cm.g.doubleclick.net https://www.google-analytics.com https://maps.googleapis.com https://www.periscope.tv https://www.pscp.tv https://ads-twitter.com https://ads-api.twitter.com https://ads-api.x.com https://media.riffsy.com https://*.giphy.com https://media.tenor.com https://c.tenor.com https://*.pscp.tv https://*.periscope.tv https://prod-periscope-profile.s3-us-west-2.amazonaws.com https://platform-lookaside.fbsbx.com https://scontent.xx.fbcdn.net https://scontent-sea1-1.xx.fbcdn.net https://*.googleusercontent.com https://t.co/1/i/adsct; manifest-src \'self\'; media-src \'self\' blob: https://twitter.com https://x.com https://*.twimg.com https://*.vine.co https://*.pscp.tv https://*.video.pscp.tv https://dhdsnappytv-vh.akamaihd.net https://pdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://mdhdsnappytv-vh.akamaihd.net https://mpdhdsnappytv-vh.akamaihd.net https://mmdhdsnappytv-vh.akamaihd.net https://dwo3ckksxlb0v.cloudfront.net; object-src \'none\'; script-src \'self\' \'unsafe-inline\' https://*.twimg.com https://recaptcha.net/recaptcha/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://client-api.arkoselabs.com/ https://www.google-analytics.com https://twitter.com https://x.com https://accounts.google.com/gsi/client https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js https://www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js https://static.ads-twitter.com \'nonce-YTg3ZWYxMjQtYzQ3NC00M2U4LTg5NjEtN2Y4MDk4MTQzYzEz\'; style-src \'self\' \'unsafe-inline\' https://accounts.google.com/gsi/style https://*.twimg.com; worker-src \'self\' blob:; report-uri https://twitter.com/i/csp_report?a=O5RXE%3D%3D%3D&ro=false' + ], + 'strict-transport-security' => [ + 'max-age=631138519', + 'max-age=631138519' + ], + 'cross-origin-opener-policy' => [ + 'same-origin-allow-popups', + 'same-origin-allow-popups' + ], + 'cross-origin-embedder-policy' => [ + 'unsafe-none', + 'unsafe-none' + ], + 'content-encoding' => [ + 'gzip', + 'gzip' + ], + 'content-length' => [ + '96' + ], + 'x-response-time' => [ + '111', + '120' + ], + 'x-connection-hash' => [ + 'd7287f618150364cbf61bba5979e8b3bb7911090ca0326bf04e7f7f5e9052e91 HTTP/2 200', + '443fe23222e9bd1a71510322785aa6ef274eb17f11b3575521a7b06e3fdae12c' + ], + 'Content-Location' => [ + 'https://x.com/pepephone/status/436461658601713664' + ], + 'X-Request-Time' => [ + '0.485 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + x.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ' +]; diff --git a/tests/cache/vimeo.com.235352744.php b/tests/cache/vimeo.com.235352744.php new file mode 100644 index 00000000..77c3e9f3 --- /dev/null +++ b/tests/cache/vimeo.com.235352744.php @@ -0,0 +1,2346 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:21 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 03:59:20 GMT' + ], + 'x-vimeo-device' => [ + 'd' + ], + 'x-frame-options' => [ + 'sameorigin' + ], + 'set-cookie' => [ + 'vuid=554709598.1762676928; expires=Thu, 08-Jun-2034 15:59:20 GMT; Max-Age=315360000; path=/; domain=.vimeo.com; secure; SameSite=None', + '_abexps=%7B%223316%22%3A%22control%22%7D; expires=Tue, 10-Jun-2025 15:59:20 GMT; Max-Age=31536000; path=/; domain=vimeo.com; SameSite=Lax', + '__cf_bm=wVoYJPRILD150aiC_w1T_gW5TOW.ZJXqsn02ww8Ntvo-1718035161-1.0.1.1-FhomwOiNYftmBIqiRTjeXWf.GQ9sddi9i8YhZ09v5vwL_1lJqWfTHPvgkcosF2vLGt_TupcKlCw8rFjaNyeDMg; path=/; expires=Mon, 10-Jun-24 16:29:21 GMT; domain=.vimeo.com; HttpOnly; Secure; SameSite=None', + '_cfuvid=epwj3pYXoPCc0eWPO1EAwzjQwRJFG7nhl2oNXnEcGoI-1718035161394-0.0.1.1-604800000; path=/; domain=.vimeo.com; HttpOnly; Secure; SameSite=None' + ], + 'x-bapp-server' => [ + 'pweb-7744dc7bbd-7bljv' + ], + 'age' => [ + '0' + ], + 'via' => [ + '1.1 varnish (Varnish/6.0), 1.1 varnish, 1.1 varnish' + ], + 'cache-control' => [ + 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ], + 'x-varnish-cache' => [ + '0' + ], + 'x-vserver' => [ + 'web-varnish-prod-varnish-12' + ], + 'x-backend-proxy' => [ + 'webproxy13' + ], + 'x-served-by' => [ + 'cache-iad-kiad7000107-IAD, cache-mad2200135-MAD' + ], + 'x-cache' => [ + 'MISS, MISS' + ], + 'x-cache-hits' => [ + '0, 0' + ], + 'x-timer' => [ + 'S1718035161.769346,VS0,VE619' + ], + 'vary' => [ + 'Accept-Encoding,x-http-method-override' + ], + 'cf-cache-status' => [ + 'DYNAMIC' + ], + 'server' => [ + 'cloudflare' + ], + 'cf-ray' => [ + '891a916aab9d1bb7-MAD' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://vimeo.com/235352744' + ], + 'X-Request-Time' => [ + '0.757 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VimeUhOh + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + +
+ +
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/vimeo.com.api-oembed.json.a647af9efa5b50781a131ff0fe77e579.php b/tests/cache/vimeo.com.api-oembed.json.a647af9efa5b50781a131ff0fe77e579.php new file mode 100644 index 00000000..d5ecc628 --- /dev/null +++ b/tests/cache/vimeo.com.api-oembed.json.a647af9efa5b50781a131ff0fe77e579.php @@ -0,0 +1,106 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:21 GMT' + ], + 'content-type' => [ + 'application/json' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'connection' => [ + 'keep-alive' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'access-control-allow-headers' => [ + 'X-Requested-With' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'sameorigin' + ], + 'last-modified' => [ + 'Sun, 09 Jun 2024 20:05:10 GMT' + ], + 'etag' => [ + 'W/"29c964a0b59cd089a82f5063b4ccb5cde17a0c30"' + ], + 'x-ua-compatible' => [ + 'IE=edge' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains; preload' + ], + 'content-security-policy-report-only' => [ + 'default-src https: data: blob: wss: \'unsafe-inline\' \'unsafe-eval\'; report-uri /_csp' + ], + 'x-bapp-server' => [ + 'pweb-88884bb8-9296-0-canary-kswpn' + ], + 'age' => [ + '82' + ], + 'via' => [ + '1.1 varnish (Varnish/6.0), 1.1 varnish, 1.1 varnish' + ], + 'cache-control' => [ + 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ], + 'x-varnish-cache' => [ + '1' + ], + 'x-vserver' => [ + 'web-varnish-prod-varnish-12' + ], + 'x-backend-proxy' => [ + 'webproxy13' + ], + 'x-served-by' => [ + 'cache-iad-kjyo7100100-IAD, cache-mad2200135-MAD' + ], + 'x-cache' => [ + 'MISS, MISS' + ], + 'x-cache-hits' => [ + '0, 0' + ], + 'x-timer' => [ + 'S1718035162.551102,VS0,VE102' + ], + 'vary' => [ + 'Accept-Encoding,x-http-method-override' + ], + 'cf-cache-status' => [ + 'DYNAMIC' + ], + 'server' => [ + 'cloudflare' + ], + 'cf-ray' => [ + '891a916f8a5d215c-MAD' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://vimeo.com/api/oembed.json?url=https%3A%2F%2Fvimeo.com%2F235352744&format=json' + ], + 'X-Request-Time' => [ + '0.186 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"video","version":"1.0","provider_name":"Vimeo","provider_url":"https:\\/\\/vimeo.com\\/","html":" +
+ +
+
+ + +

Dave Ross: Optimize Image Files Like a Pro

+ +
+ +
+ +
+
+ +
+
+
+
+

+ One response on “Dave Ross: Optimize Image Files Like a Pro

+ +
    +
  1. + + \'\' Chad Warner + +
    + + + + + +
    + +

    Some of the tools Dave mentioned are Mac-only. Windows users, what are your favorite tools for image optimization?

    +

    Like

    +
    +
    +
  2. + +
+
+

Continue the discussion

+ + +
+ + + +

+
+
+
+ +
+
Published
+

September 6, 2013

+ +

Images, even small ones, can be the biggest files that make up your site. Learn the tools, plugins, and theming techniques you’ll want to start using to shrink your page load times and save your mobile users a few bucks without sacrificing image quality.

+

Presentation Slides »

+

Rate this:

+
Event

WordCamp Providence 2013 26

Speakers

Dave Ross 3

Tags

images 53

Language

English 10586

Download
+
+MP4: Low, Med, High, Original
OGG: Low
+
Subtitles
Subtitle this video → +
Producer
+ + + +
+
+ + +
+ + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/www.23hq.com.23-oembed.395a90e7310fd895bdb40e159a59cf07.php b/tests/cache/www.23hq.com.23-oembed.395a90e7310fd895bdb40e159a59cf07.php new file mode 100644 index 00000000..2e258e19 --- /dev/null +++ b/tests/cache/www.23hq.com.23-oembed.395a90e7310fd895bdb40e159a59cf07.php @@ -0,0 +1,46 @@ + [ + 'server' => [ + 'nginx' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:27:30 GMT' + ], + 'content-type' => [ + 'application/json' + ], + 'content-length' => [ + '570' + ], + 'connection' => [ + 'keep-alive' + ], + 'set-cookie' => [ + 'ad_session_id=46534443135%2c0%2c0+%7b983+1617551250+7741022AB787914DAFE57F53AA44F8DA7A18A857%7d; Path=/; Max-Age=1200' + ], + 'expires' => [ + 'Sun, 04 Apr 2021 15:27:30 GMT' + ], + 'pragma' => [ + 'no-cache' + ], + 'cache-control' => [ + 'no-cache' + ], + 'mime-version' => [ + '1.0' + ], + 'Content-Location' => [ + 'http://www.23hq.com/23/oembed?format=json&url=http%3A%2F%2Fwww.23hq.com%2FZzleeper%2Fphoto%2F16600737' + ], + 'X-Request-Time' => [ + '0.149 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0", "type":"photo", "title":"På god väns inrådan kommer det även bultförband vid pilarna. Låter bra tycker jag. (Better safe than sorry)", "author_name":"Zzleeper", "author_url":"http://www.23hq.com/Zzleeper/", "cache_age":3600, "provider_name":23, "provider_url":"http://www.23hq.com/", "width":756, "height":567, "url":"http://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg", "thumbnail_width":756, "thumbnail_height":567, "thumbnail_url":"http://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg"}' +]; diff --git a/tests/cache/www.23hq.com.23-oembed.5e3c57c18abae8c996fd98ef1dc684fe.php b/tests/cache/www.23hq.com.23-oembed.5e3c57c18abae8c996fd98ef1dc684fe.php new file mode 100644 index 00000000..2826303c --- /dev/null +++ b/tests/cache/www.23hq.com.23-oembed.5e3c57c18abae8c996fd98ef1dc684fe.php @@ -0,0 +1,43 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:50 GMT' + ], + 'content-type' => [ + 'application/json' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 15:58:50 GMT' + ], + 'pragma' => [ + 'no-cache' + ], + 'cache-control' => [ + 'no-cache' + ], + 'mime-version' => [ + '1.0' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://www.23hq.com/23/oembed?format=json&url=https%3A%2F%2Fwww.23hq.com%2FZzleeper%2Fphoto%2F16600737' + ], + 'X-Request-Time' => [ + '0.189 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0", "type":"photo", "title":"På god väns inrådan kommer det även bultförband vid pilarna. Låter bra tycker jag. (Better safe than sorry)", "author_name":"Zzleeper", "author_url":"https://www.23hq.com/Zzleeper/", "cache_age":3600, "provider_name":23, "provider_url":"http://www.23hq.com/", "width":756, "height":567, "url":"https://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg", "thumbnail_width":756, "thumbnail_height":567, "thumbnail_url":"https://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg"}' +]; diff --git a/tests/cache/www.23hq.com.zzleeper-photo-16600737.php b/tests/cache/www.23hq.com.zzleeper-photo-16600737.php new file mode 100644 index 00000000..4ee715e9 --- /dev/null +++ b/tests/cache/www.23hq.com.zzleeper-photo-16600737.php @@ -0,0 +1,649 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:49 GMT', + 'Mon, 10 Jun 2024 15:58:50 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '164' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://www.23hq.com/Zzleeper/photo/16600737%20%20HTTP/2%20200' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'set-cookie' => [ + 'ad_session_id=51296703557%2c0%2c0+%7b410+1718036330+CD81FE32CAA446A2193CD5C4284DCD1C00135567%7d; Path=/; Max-Age=1200', + 'ad_locale=es_ES; Path=/; Expires=Mon, 01-Jan-2035 01:00:00 GMT', + 'incr_photo_id=16600737; Path=/' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 15:58:50 GMT' + ], + 'pragma' => [ + 'no-cache' + ], + 'cache-control' => [ + 'no-cache' + ], + 'mime-version' => [ + '1.0' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://www.23hq.com/Zzleeper/photo/16600737' + ], + 'X-Request-Time' => [ + '0.668 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + 23: På god väns inrådan kommer det även bultförband vid... - Zzleeper + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + + +
+
+ + +
+ +
+ + + + + + + +
+ +
+ + + + + +
+ + +
+
+ +
+
+ +
+
+ +
+
+
+ + + + + + +
+
+ + +
+
+
På god väns inrådan kommer det även bultförband vid pilarna. Låter bra tycker jag. (Better safe than sorry)
+ +
+ +
+ + + + + +
+

+ + + +
+
+ +
+ + + Agregue un comentario... + + + + + + + + + +
Tu nombre:
Tu correo eletrónico:
+ +
+ + + + +
+
+ + + +
+ + + +
+
+ + + + + + + + + + + + +



+
+
+
+ +
+
+ +
+ + + + + + + +
+

Sobre 23

+ +
+ Sobre 23
+
¿Qué es 23 y quién está detrás?
+
+
+ Recientes
+
Descubre el mundo desde un ángulo distinto.
Aquí hay un puñado de las últimas fotos de alrededor del mundo.
+
+
+ Buscar
+
Buscar 23
+
+
+ Ayuda / Foro de discusión
+
Obtén ayuda o comparte tus ideas para mejorar 23
+
+
+ 23 Blog / 23 on Twitter
+
Mensajes y observaciones del Equipo 23
+
+
+ Términos de uso
+
Para qué puede utilizarse 23 y para qué no
+
+
+ Más servicios de 23
+
También ayudamos a la gente a compartir fotos en sus vidas profesionales
+
+ +
+
    + +
  • Basque (ES)
  • + +
  • Bulgarian (BG)
  • + +
  • Chinese (CN)
  • + +
  • Chinese (TW)
  • + +
  • Danish (DK)
  • + +
  • Dutch (NL)
  • + +
  • English (US)
  • + +
  • French (FR)
  • + +
  • Galician (ES)
  • + +
  • German (DE)
  • + +
  • Italian (IT)
  • + +
  • Norwegian (NO)
  • + +
  • Polish (PL)
  • + +
  • Portuguese (PT)
  • + +
  • Russian (RU)
  • + +
  • Spanish (ES)
  • + +
  • Swedish (SE)
  • + +
+
+ + +
+

Fotos populares del momento

+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/www.abanca.com.gl.php b/tests/cache/www.abanca.com.gl.php new file mode 100644 index 00000000..4fd26894 --- /dev/null +++ b/tests/cache/www.abanca.com.gl.php @@ -0,0 +1,259 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:25 GMT', + 'Mon, 10 Jun 2024 15:58:25 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '162', + '55042' + ], + 'location' => [ + 'https://www.abanca.com/gl/' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains', + 'max-age=31536000; includeSubDomains' + ], + 'cache-control' => [ + 'no-store', + 'no-store' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'x-xss-protection' => [ + '1; mode=block', + '1; mode=block' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin', + 'strict-origin-when-cross-origin' + ], + 'permissions-policy' => [ + 'accelerometer=(), camera=(), geolocation=(self), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()', + 'accelerometer=(), camera=(), geolocation=(self), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()' + ], + 'expect-ct' => [ + 'enforce, max-age=300, report-uri=\'/api/v1 /report-uri/expect-ct\'', + 'enforce, max-age=300, report-uri=\'/api/v1 /report-uri/expect-ct\'' + ], + 'content-security-policy' => [ + 'default-src \'self\' *.abanca.io llamamegratis.es/ suite.conver.fit/ privacyportal-de.onetrust.com https://abancawt.infobolsa.es https://abancawt.bmeinntech.es *.2o7.net *.omtrdc.net *.tt.omtrdc.net https://assets.adobedtm.com *.adobe.com smetrics.abanca.com metrics.abanca.com smetrics.cuentasclaras.es metrics.cuentasclaras.es target.abanca.com target.cuentasclaras.com https://c.bing.com *.clarity.ms *.mouseflow.com;script-src \'self\' \'unsafe-inline\' \'unsafe-eval\' *.googlesyndication.com *.abanca.io llamamegratis.es/ suite.conver.fit/ www.google-analytics.com maps.googleapis.com cdnjs.cloudflare.com abanca.inbenta.com www.googletagmanager.com cdn.cookielaw.org code.jquery.com cstatic.weborama.fr www.google-analytics.com www.googleadservices.com static.ads-twitter.com bat.bing.com connect.facebook.net analytics.twitter.com googleads.g.doubleclick.net optimize.google.com platform.twitter.com cdn.syndication.twimg.com tagmanager.google.com ssl.google-analytics.com www.google.com az416426.vo.msecnd.net geolocation.onetrust.com https://*.demdex.net https://cm.everesttech.net https://assets.adobedtm.com https://cdn.tt.omtrdc.net https://activitymap.adobe.com *.opinator.com cloud.weborama.design sdk.inbenta.io acdn.adnxs.com resources.digital-cloud.medallia.eu https://c.bing.com *.clarity.ms *.kampyle.com *.medallia.eu opticksprotection.com analytics.tiktok.com *.mouseflow.com app.sealmetrics.com;style-src \'self\' \'unsafe-inline\' *.abanca.io llamamegratis.es/ suite.conver.fit/ fonts.googleapis.com cdnjs.cloudflare.com abanca.inbenta.com cdn.cookielaw.org optimize.google.com cdn.abanca.io platform.twitter.com *.twimg.com tagmanager.google.com https://cdn.tt.omtrdc.net sdk.inbenta.io *.kampyle.com y *.medallia.eu;img-src \'self\' *.doubleclick.net *.abanca.io *.googlesyndication.com inbenta.com static-or00.inbenta.com llamamegratis.es/ suite.conver.fit/ www.google-analytics.com maps.googleapis.com maps.gstatic.com stats.g.doubleclick.net insight.adsrvr.org cdn.abanca.io data: t.co bat.bing.com www.google.com www.google.es www.google-analytics.com www.facebook.com stats.g.doubleclick.net www.googletagmanager.com i.ytimg.com optimize.google.com *.staticflickr.com *.staticflickr.com syndication.twitter.com *.twimg.com platform.twitter.com contenidos.infobolsa.es contenidos.bmeinntech.es ssl.gstatic.com www.gstatic.com googleads.g.doubleclick.net tbl.tradedoubler.com *.blob.core.windows.net staticcdn.ald-automotive.es cdn.cookielaw.org https://*.demdex.net https://cm.everesttech.net https://assets.adobedtm.com *.omtrdc.net smetrics.abanca.com metrics.abanca.com smetrics.cuentasclaras.es metrics.cuentasclaras.es target.abanca.com target.cuentasclaras.com scene7.com *.clarity.ms *.opinator.com *.adnxs.com *.kampyle.com y *.medallia.eu opticksstatic.com *.mouseflow.com;media-src \'self\' www.abanca.io inbenta.com static-or00.inbenta.com cdn.abanca.io;font-src \'self\' *.abanca.io llamamegratis.es/ suite.conver.fit/ fonts.gstatic.com abanca.inbenta.com cdn.abanca.io cdn.inbenta.io *.kampyle.com y *.medallia.eu *.mouseflow.com;frame-src \'self\' *.doubleclick.net www.youtube-nocookie.com llamamegratis.es mediadiamondes.solution.weborama.fr optimize.google.com www.facebook.com maps.google.com www.google.com www.youtube.com platform.twitter.com syndication.twitter.com w.soundcloud.com bid.g.doubleclick.net *.fls.doubleclick.net https://*.demdex.net esredegal1.solution.weborama.fr https://activitymap.adobe.com/ *.opinator.com *.kampyle.com y *.medallia.eu *.mouseflow.com;connect-src \'self\' *.googlesyndication.com *.abanca.io api.abanca.com www.google-analytics.com *.infobolsa.es *.bmeinntech.es suite.conver.fit privacyportal-de.onetrust.com api-stratos-test.azurewebsites.net aldesmarvin.blob.core.windows.net dc.services.visualstudio.com api-stratos.aldes.io api-stratos-sbx.aldes.io cdn.cookielaw.org stats.g.doubleclick.net https://*.demdex.net https://cm.everesttech.net https://assets.adobedtm.com *.omtrdc.net smetrics.abanca.com wf.frontend.weborama.fr ams3.digitaloceanspaces.com api.inbenta.io *.clarity.ms api-gce2.inbenta.io cookies-data.onetrust.io *.kampyle.com y *.medallia.eu region1.google-analytics.com region1.analytics.google.com opticksprotection.com analytics.tiktok.com cdp.abanca.com cdpdev.abanca.com maps.googleapis.com *.mouseflow.com geolocation.onetrust.com;base-uri \'self\';child-src \'self\' *.mouseflow.com;object-src \'none\'', + 'default-src \'self\' *.abanca.io llamamegratis.es/ suite.conver.fit/ privacyportal-de.onetrust.com https://abancawt.infobolsa.es https://abancawt.bmeinntech.es *.2o7.net *.omtrdc.net *.tt.omtrdc.net https://assets.adobedtm.com *.adobe.com smetrics.abanca.com metrics.abanca.com smetrics.cuentasclaras.es metrics.cuentasclaras.es target.abanca.com target.cuentasclaras.com https://c.bing.com *.clarity.ms *.mouseflow.com;script-src \'self\' \'unsafe-inline\' \'unsafe-eval\' *.googlesyndication.com *.abanca.io llamamegratis.es/ suite.conver.fit/ www.google-analytics.com maps.googleapis.com cdnjs.cloudflare.com abanca.inbenta.com www.googletagmanager.com cdn.cookielaw.org code.jquery.com cstatic.weborama.fr www.google-analytics.com www.googleadservices.com static.ads-twitter.com bat.bing.com connect.facebook.net analytics.twitter.com googleads.g.doubleclick.net optimize.google.com platform.twitter.com cdn.syndication.twimg.com tagmanager.google.com ssl.google-analytics.com www.google.com az416426.vo.msecnd.net geolocation.onetrust.com https://*.demdex.net https://cm.everesttech.net https://assets.adobedtm.com https://cdn.tt.omtrdc.net https://activitymap.adobe.com *.opinator.com cloud.weborama.design sdk.inbenta.io acdn.adnxs.com resources.digital-cloud.medallia.eu https://c.bing.com *.clarity.ms *.kampyle.com *.medallia.eu opticksprotection.com analytics.tiktok.com *.mouseflow.com app.sealmetrics.com;style-src \'self\' \'unsafe-inline\' *.abanca.io llamamegratis.es/ suite.conver.fit/ fonts.googleapis.com cdnjs.cloudflare.com abanca.inbenta.com cdn.cookielaw.org optimize.google.com cdn.abanca.io platform.twitter.com *.twimg.com tagmanager.google.com https://cdn.tt.omtrdc.net sdk.inbenta.io *.kampyle.com y *.medallia.eu;img-src \'self\' *.doubleclick.net *.abanca.io *.googlesyndication.com inbenta.com static-or00.inbenta.com llamamegratis.es/ suite.conver.fit/ www.google-analytics.com maps.googleapis.com maps.gstatic.com stats.g.doubleclick.net insight.adsrvr.org cdn.abanca.io data: t.co bat.bing.com www.google.com www.google.es www.google-analytics.com www.facebook.com stats.g.doubleclick.net www.googletagmanager.com i.ytimg.com optimize.google.com *.staticflickr.com *.staticflickr.com syndication.twitter.com *.twimg.com platform.twitter.com contenidos.infobolsa.es contenidos.bmeinntech.es ssl.gstatic.com www.gstatic.com googleads.g.doubleclick.net tbl.tradedoubler.com *.blob.core.windows.net staticcdn.ald-automotive.es cdn.cookielaw.org https://*.demdex.net https://cm.everesttech.net https://assets.adobedtm.com *.omtrdc.net smetrics.abanca.com metrics.abanca.com smetrics.cuentasclaras.es metrics.cuentasclaras.es target.abanca.com target.cuentasclaras.com scene7.com *.clarity.ms *.opinator.com *.adnxs.com *.kampyle.com y *.medallia.eu opticksstatic.com *.mouseflow.com;media-src \'self\' www.abanca.io inbenta.com static-or00.inbenta.com cdn.abanca.io;font-src \'self\' *.abanca.io llamamegratis.es/ suite.conver.fit/ fonts.gstatic.com abanca.inbenta.com cdn.abanca.io cdn.inbenta.io *.kampyle.com y *.medallia.eu *.mouseflow.com;frame-src \'self\' *.doubleclick.net www.youtube-nocookie.com llamamegratis.es mediadiamondes.solution.weborama.fr optimize.google.com www.facebook.com maps.google.com www.google.com www.youtube.com platform.twitter.com syndication.twitter.com w.soundcloud.com bid.g.doubleclick.net *.fls.doubleclick.net https://*.demdex.net esredegal1.solution.weborama.fr https://activitymap.adobe.com/ *.opinator.com *.kampyle.com y *.medallia.eu *.mouseflow.com;connect-src \'self\' *.googlesyndication.com *.abanca.io api.abanca.com www.google-analytics.com *.infobolsa.es *.bmeinntech.es suite.conver.fit privacyportal-de.onetrust.com api-stratos-test.azurewebsites.net aldesmarvin.blob.core.windows.net dc.services.visualstudio.com api-stratos.aldes.io api-stratos-sbx.aldes.io cdn.cookielaw.org stats.g.doubleclick.net https://*.demdex.net https://cm.everesttech.net https://assets.adobedtm.com *.omtrdc.net smetrics.abanca.com wf.frontend.weborama.fr ams3.digitaloceanspaces.com api.inbenta.io *.clarity.ms api-gce2.inbenta.io cookies-data.onetrust.io *.kampyle.com y *.medallia.eu region1.google-analytics.com region1.analytics.google.com opticksprotection.com analytics.tiktok.com cdp.abanca.com cdpdev.abanca.com maps.googleapis.com *.mouseflow.com geolocation.onetrust.com;base-uri \'self\';child-src \'self\' *.mouseflow.com;object-src \'none\'' + ], + 'x-envoy-upstream-service-time' => [ + '22', + '19' + ], + 'server' => [ + 'volt-adc HTTP/2 200', + 'volt-adc' + ], + 'last-modified' => [ + 'Mon, 10 Jun 2024 14:21:07 GMT' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'etag' => [ + '"66670bd3-d702"' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://www.abanca.com/gl/' + ], + 'X-Request-Time' => [ + '0.181 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' ABANCA banca online para particulares e empresas | ABANCA
' +]; diff --git a/tests/cache/www.aol.com.video-view-pile-of-recovering-foster-kittens-is-purrfect-595fe75985eb42109b69bedb.php b/tests/cache/www.aol.com.video-view-pile-of-recovering-foster-kittens-is-purrfect-595fe75985eb42109b69bedb.php new file mode 100644 index 00000000..0cda45df --- /dev/null +++ b/tests/cache/www.aol.com.video-view-pile-of-recovering-foster-kittens-is-purrfect-595fe75985eb42109b69bedb.php @@ -0,0 +1,428 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:30 GMT', + 'Mon, 10 Jun 2024 15:58:30 GMT' + ], + 'strict-transport-security' => [ + 'max-age=31536000', + 'max-age=31536000' + ], + 'server' => [ + 'ATS', + 'ATS' + ], + 'cache-control' => [ + 'no-store', + 'no-cache, no-store, private, must-revalidate' + ], + 'location' => [ + 'https://www.aol.com/video/' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'content-language' => [ + 'en' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade', + 'no-referrer-when-downgrade' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'content-length' => [ + '308' + ], + 'age' => [ + '0', + '0' + ], + 'expect-ct' => [ + 'max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only"', + 'max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only"' + ], + 'x-xss-protection' => [ + '1; mode=block', + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff HTTP/2 200', + 'nosniff' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'content-security-policy' => [ + 'upgrade-insecure-requests; block-all-mixed-content; sandbox allow-modals allow-forms allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox allow-presentation allow-orientation-lock allow-pointer-lock;' + ], + 'Content-Location' => [ + 'https://www.aol.com/video/' + ], + 'X-Request-Time' => [ + '0.324 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'AOL Video - Serving the best video content from AOL and around the web - AOL.com

More InfoLess Info

+ + + + + + + + + + + + + +' +]; diff --git a/tests/cache/www.bbc.co.uk.news-uk-54222286.php b/tests/cache/www.bbc.co.uk.news-uk-54222286.php new file mode 100644 index 00000000..9370862c --- /dev/null +++ b/tests/cache/www.bbc.co.uk.news-uk-54222286.php @@ -0,0 +1,164 @@ + [ + 'content-type' => [ + 'text/html' + ], + 'belfrage-cache-status' => [ + 'MISS' + ], + 'bid' => [ + 'joan' + ], + 'brequestid' => [ + '1eaeb3ca48c644db902278f7f3158b6d' + ], + 'bsig' => [ + 'b6c159455f51f02aa34dc0a9773a202f' + ], + 'cache-control' => [ + 'public, stale-if-error=90, stale-while-revalidate=30, max-age=5' + ], + 'content-encoding' => [ + 'gzip' + ], + 'content-return-type' => [ + 'STY' + ], + 'content-security-policy' => [ + 'default-src \'none\'; script-src \'strict-dynamic\' \'nonce-2/ZyywMhTzcnc1ZOZkj3y2wIM4Oa85FlkIYy3uFtznAzEeSTdP\' \'self\' \'report-sample\' \'unsafe-inline\' assets.wearehearken.eu cdn.syndication.twimg.com connect.facebook.net c.files.bbci.co.uk emp.bbci.co.uk ems.wearehearken.eu modules.wearehearken.eu mybbc-analytics.files.bbci.co.uk nav.files.bbci.co.uk news.files.bbci.co.uk platform.twitter.com public.flourish.studio static.bbc.co.uk static.bbci.co.uk static.chartbeat.com static2.chartbeat.com www.bbc.co.uk www.instagram.com www.ons.gov.uk gn-web-assets.api.bbc.com www.google-analytics.com bitesize.files.bbci.co.uk www.tiktok.com lf16-tiktok-web.ttwstatic.com static.files.bbci.co.uk; img-src \'self\' https: data:; font-src c.files.bbci.co.uk gel.files.bbci.co.uk static.files.bbci.co.uk static.bbci.co.uk news.files.bbci.co.uk ws-downloads.files.bbci.co.uk bitesize.files.bbci.co.uk; style-src branding.files.bbci.co.uk cdn.riddle.com flo.uri.sh news.files.bbci.co.uk platform.twitter.com static.bbc.co.uk static.bbci.co.uk static.files.bbci.co.uk ton.twimg.com www.riddle.com \'unsafe-inline\' lf16-tiktok-web.ttwstatic.com; frame-src \'self\' bbc001.carto.com bbc003.carto.com bbc-maps.carto.com cdn.riddle.com chartbeat.com emp.bbc.co.uk emp.bbc.com flo.uri.sh graphics.reuters.com www.reuters.com m.facebook.com news.files.bbci.co.uk personaltaxcalculator2.deloittecloud.co.uk platform.twitter.com public.flourish.studio static2.chartbeat.com syndication.twitter.com web.facebook.com www.bbc.co.uk www.facebook.com www.instagram.com www.tiktok.com www.ons.gov.uk www.riddle.com www.youtube.com www.youtube-nocookie.com toybox.tools.bbc.co.uk uk-script.dotmetrics.net ssp-app-uk.votenow.tv ssp-app-uktest.votenow.tv session.test.bbc.co.uk session.bbc.co.uk; object-src \'none\'; manifest-src static.files.bbci.co.uk bitesize.files.bbci.co.uk; media-src \'self\' blob: https:; connect-src \'self\' https:; child-src blob:; base-uri \'none\'; form-action \'self\' platform.twitter.com syndication.twitter.com uk-script.dotmetrics.net/DeviceInfo.dotmetrics; frame-ancestors \'none\'; upgrade-insecure-requests; report-to default; report-uri https://webcore.bbc-reporting-api.app/report-endpoint;' + ], + 'feature-policy' => [ + 'accelerometer \'none\'; autoplay \'self\' https://emp.bbc.com https://emp.bbc.co.uk http://emp.bbc.com http://emp.bbc.co.uk; camera \'none\'; document-domain \'self\' https://emp.bbc.com https://emp.bbc.co.uk http://emp.bbc.com http://emp.bbc.co.uk; encrypted-media \'none\'; fullscreen \'self\' https://emp.bbc.com https://emp.bbc.co.uk http://emp.bbc.com http://emp.bbc.co.uk; geolocation \'none\'; gyroscope \'none\'; magnetometer \'none\'; microphone \'none\'; midi \'none\'; payment \'none\'; picture-in-picture \'self\' https://emp.bbc.com https://emp.bbc.co.uk http://emp.bbc.com http://emp.bbc.co.uk; screen-wake-lock \'none\'; sync-xhr \'self\'; usb \'none\'; xr-spatial-tracking \'none\'' + ], + 'nel' => [ + '{"report_to":"default","max_age":2592000,"include_subdomains":true,"failure_fraction":0.25}' + ], + 'permissions-policy' => [ + 'accelerometer=(), autoplay=(self "https://emp.bbc.com/" "https://emp.bbc.co.uk/" "http://emp.bbc.com/" "http://emp.bbc.co.uk/"), camera=(), document-domain=(self "https://emp.bbc.com/" "https://emp.bbc.co.uk/" "http://emp.bbc.com/" "http://emp.bbc.co.uk/"), encrypted-media=(), fullscreen=(self "https://emp.bbc.com/" "https://emp.bbc.co.uk/" "http://emp.bbc.com/" "http://emp.bbc.co.uk/"), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(self "https://emp.bbc.com/" "https://emp.bbc.co.uk/" "http://emp.bbc.com/" "http://emp.bbc.co.uk/"), screen-wake-lock=(), sync-xhr=(self), usb=(), xr-spatial-tracking=()', + 'browsing-topics=(), join-ad-interest-group=(), run-ad-auction=()' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'req-svc-chain' => [ + 'FASTLY,GTM,BELFRAGE' + ], + 'via' => [ + '1.1 BBC-GTM, 1.1 Belfrage, 1.1 varnish' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'DENY' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'origin-agent-cluster' => [ + '?0' + ], + 'x-bbc-edge-cache-status' => [ + 'MISS' + ], + 'x-bbc-origin-response-status' => [ + '200' + ], + 'report-to' => [ + '{"group":"default","max_age":2592000,"endpoints":[{"url":"https://default.bbc-reporting-api.app/report-endpoint","priority":1}],"include_subdomains":true}' + ], + 'server' => [ + 'BBC-GTM' + ], + 'strict-transport-security' => [ + 'max-age=31536000; preload' + ], + 'fastly-restarts' => [ + '1' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:33 GMT' + ], + 'x-fastly-cache-status' => [ + 'HIT-STALE-CLUSTER' + ], + 'x-served-by' => [ + 'cache-mad2200087-MAD' + ], + 'x-cache' => [ + 'HIT' + ], + 'x-cache-hits' => [ + '0' + ], + 'x-timer' => [ + 'S1718035173.212318,VS0,VE2' + ], + 'x-fastly-pre-flight-cache' => [ + 'MISS, HIT' + ], + 'x-fastly-pre-flight-cache-status' => [ + 'HIT' + ], + 'x-cache-age' => [ + '83' + ], + 'x-lb-nocache' => [ + 'true' + ], + 'vary' => [ + 'X-BBC-Edge-Scheme,Accept-Encoding' + ], + 'alt-svc' => [ + 'h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400' + ], + 'content-length' => [ + '56693' + ], + 'Content-Location' => [ + 'https://www.bbc.co.uk/news/uk-54222286' + ], + 'X-Request-Time' => [ + '0.081 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Coronavirus: £10,000 fines for failing to self-isolate and lockdown life in photos - BBC News

Coronavirus: £10,000 fines for failing to self-isolate and lockdown life in photos

  • Published

Here are five things you need to know about the coronavirus pandemic this Sunday morning. We'll have another update for you on Monday.

1. £10,000 fines for failing to self-isolate

The government has said it will introduce a new legal duty requiring people in England to self-isolate if they test positive for coronavirus, or are traced as a close contact. From 28 September, those who refuse an order to self-isolate could be fined up to £10,000. The new measures also include a one-off support payment of £500 for those on lower incomes. The PM is still considering tightening restrictions further after a surge in cases across the UK - another 4,422 cases were recorded on Saturday.

2. BA accused of snubbing refund request

Lesley Anderson had been due to fly from Glasgow to London to celebrate her birthday, but disruption caused by the pandemic meant her British Airways flights were cancelled. She says a voucher was issued "automatically" after she selected "cancel and refund flight". BA has said there is "no way" that vouchers can be issued without customers requesting them. You can read the full story here from Ms Anderson, who is the latest person to accuse the airline of misleading its customers.

Image source, Getty Images

3. Singapore rolls out tracing tokens

Thousands of devices which can track where a person has been and who they have interacted with are being distributed in Singapore. The small Bluetooth device is meant for those who do not own smartphones and cannot use a contact tracing app. Authorities say the token helps vulnerable groups to feel safer when out and about.

Media caption,

The Covid tracing tokens being issued in Singapore

4. Political party conferences in a Covid world

Coronavirus has robbed politicos of the chance to mingle in their hundreds at party conferences this autumn. Instead, Conservatives, Labourites and Liberal Democrats will have to watch their leaders speak via Zoom. The parties insist the events will be as vibrant and interesting as possible, but, as Labour's gets under way this weekend, what are the big things to look out for and how much has changed?

Image source, PA Media

5. Lockdown life in photos

Twenty photos capturing life during lockdown have been selected as part of a competition to feature on a video with reggae band UB40. The winning image was of a deserted dual carriageway by Jack Crook. See more of the top entries.

Image source, Jack Crook

And don't forget...

Find more information, advice and guides on our coronavirus page.

In winter, a blocked or runny nose, a sore throat and a cough are common, so how do you know if you have Covid-19? Check your symptoms here.

Image source, BBC

What questions do you have about coronavirus?

In some cases, your question will be published, displaying your name, age and location as you provide it, unless you state otherwise. Your contact details will never be published. Please ensure you have read our terms & conditions and privacy policy.

Use this form to ask your question:

+ + + +
+ + +

If you are reading this page and can't see the form you will need to visit the mobile version of the BBC website to submit your question or send them via email to YourQuestions@bbc.co.uk, external. Please include your name, age and location with any question you send in.

' +]; diff --git a/tests/cache/www.dailymotion.com.services-oembed.00317ddeb724678c2e865f13b34517a7.php b/tests/cache/www.dailymotion.com.services-oembed.00317ddeb724678c2e865f13b34517a7.php new file mode 100644 index 00000000..75ef6d28 --- /dev/null +++ b/tests/cache/www.dailymotion.com.services-oembed.00317ddeb724678c2e865f13b34517a7.php @@ -0,0 +1,55 @@ + [ + 'cache-control' => [ + 'no-cache' + ], + 'content-encoding' => [ + 'gzip' + ], + 'content-length' => [ + '339' + ], + 'content-security-policy' => [ + 'upgrade-insecure-requests' + ], + 'content-security-policy-report-only' => [ + 'default-src https: blob: wss: data: android-webview-video-poster: android-webview: chrome-extension: safari-extension: \'unsafe-eval\' \'unsafe-inline\'; report-uri https://www.dailymotion.com/content_security_policy_report_uri' + ], + 'content-type' => [ + 'application/json' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:43 GMT' + ], + 'referrer-policy' => [ + 'no-referrer-when-downgrade' + ], + 'server' => [ + 'DMS/1.0.42' + ], + 'server-timing' => [ + 'total;dur=16, dc;desc="dc3"' + ], + 'strict-transport-security' => [ + 'max-age=31708800; includeSubDomains; preload' + ], + 'timing-allow-origin' => [ + '*' + ], + 'vary' => [ + 'X-DM-SSL,Accept-Encoding' + ], + 'Content-Location' => [ + 'https://www.dailymotion.com/services/oembed?url=https%3A%2F%2Fwww.dailymotion.com%2Fvideo%2Fxy0wd&format=json' + ], + 'X-Request-Time' => [ + '0.127 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"video","version":"1.0","provider_name":"Dailymotion","provider_url":"https:\\/\\/www.dailymotion.com","title":"Chats paresseux","description":"","author_name":"jeanbamin","author_url":"https:\\/\\/www.dailymotion.com\\/jeanbamin","width":480,"height":360,"html":"\'),s.close(),u=s.w.frames[0].document,t=u.createElement("div")}catch(e){t=o.createElement("div"),u=o.body}var f=function(n){return function(){var r=Array.prototype.slice.call(arguments,0);r.unshift(t),u.appendChild(t),t.addBehavior("#default#userData"),t.load(i);var o=n.apply(e,r);return u.removeChild(t),o}},d=new RegExp("[!\\"#$%&\'()*+,/\\\\\\\\:;<=>?@[\\\\]^`{|}~]","g"),l=function(t){return t.replace(/^d/,"___$&").replace(d,"___")};e.set=f((function(t,n,r){return n=l(n),void 0===r?e.remove(n):(t.setAttribute(n,e.serialize(r)),t.save(i),r)})),e.get=f((function(t,n,r){n=l(n);var o=e.deserialize(t.getAttribute(n));return void 0===o?r:o})),e.remove=f((function(t,e){e=l(e),t.removeAttribute(e),t.save(i)})),e.clear=f((function(t){var e=t.XMLDocument.documentElement.attributes;t.load(i);for(var n=e.length-1;n>=0;n--)t.removeAttribute(e[n].name);t.save(i)})),e.getAll=function(t){var n={};return e.forEach((function(t,e){n[t]=e})),n},e.forEach=f((function(t,n){for(var r,o=t.XMLDocument.documentElement.attributes,i=0;r=o[i];++i)n(r.name,e.deserialize(t.getAttribute(r.name)))}))}try{var p="__storejs__";e.set(p,p),e.get(p)!=p&&(e.disabled=!0),e.remove(p)}catch(t){e.disabled=!0}return e.enabled=!e.disabled,e},void 0===(i="function"==typeof r?r.apply(e,o):r)||(t.exports=i)}).call(this,n("yLpj"))},fpOl:function(t,e,n){"use strict";n.d(e,"a",(function(){return r})),n.d(e,"d",(function(){return o})),n.d(e,"e",(function(){return i})),n.d(e,"f",(function(){return c})),n.d(e,"g",(function(){return a})),n.d(e,"h",(function(){return u})),n.d(e,"i",(function(){return s})),n.d(e,"b",(function(){return f})),n.d(e,"c",(function(){return d})),n.d(e,"k",(function(){return l})),n.d(e,"j",(function(){return p}));var r="dev",o="stage-01",i="stage-33",c="stage-44",a="stage-47",u="stage-52",s="stage-53",f="preprod",d="prod";function l(){return"prod".match(/stage-[0-9]{2}/)}function p(t){return t.includes("prod")}},hEhO:function(t,e,n){"use strict";var r=0;e.a=()=>r+=1},iKNE:function(t,e,n){"use strict";n.d(e,"c",(function(){return r})),n.d(e,"b",(function(){return o})),n.d(e,"h",(function(){return i})),n.d(e,"d",(function(){return c})),n.d(e,"e",(function(){return a})),n.d(e,"j",(function(){return u})),n.d(e,"i",(function(){return s})),n.d(e,"m",(function(){return f})),n.d(e,"g",(function(){return d})),n.d(e,"f",(function(){return l})),n.d(e,"l",(function(){return p})),n.d(e,"k",(function(){return _})),n.d(e,"a",(function(){return m})),n.d(e,"o",(function(){return y})),n.d(e,"p",(function(){return v})),n.d(e,"q",(function(){return g})),n.d(e,"n",(function(){return h})),n.d(e,"r",(function(){return O}));var r="client_token",o="access_token",i="refresh_token",c="dmaid",a="dmt",u="sid",s="sdx",f="v1st",d="lang",l="ff",p="ts",_="dm-euconsent-v2",m={domain:".dailymotion.com"},y=2592e3,v=3*y,g=6*y,h=13*y,O={domain:".dailymotion.com",httpOnly:!1,maxAge:h,path:"/"}},"iVi/":function(t,e,n){"use strict";e.parse=function(t,e){if("string"!=typeof t)throw new TypeError("argument str must be a string");for(var n={},o=e||{},i=t.split(";"),a=o.decode||r,u=0;u0&&void 0!==arguments[0]?arguments[0]:{},e=arguments.length>1?arguments[1]:void 0;return Object.keys(t).reduce(((n,o)=>{if(o.startsWith(e)){var i=o.substring(e.length),c=t[o];n[i]=r.includes(c)}return n}),{})}},qytn:function(t,e,n){"use strict";n.r(e),n.d(e,"DAILYMOTION_PROD_URL",(function(){return r})),n.d(e,"DAILYMOTION_PREPROD_URL",(function(){return o})),n.d(e,"BASE_URL",(function(){return i})),n.d(e,"NOT_FOUND",(function(){return c})),n.d(e,"EMAIL_LOGIN_URL",(function(){return a})),n.d(e,"EMAIL_VALIDATION_URL",(function(){return u})),n.d(e,"ACTIVATION_URL",(function(){return s})),n.d(e,"EMAIL_REPORT_VERIFICATION_URL",(function(){return f})),n.d(e,"PASSWORD_RECOVER_URL",(function(){return d})),n.d(e,"PASSWORD_SET_URL",(function(){return l})),n.d(e,"PASSWORD_REINFORCE_URL",(function(){return p})),n.d(e,"CHANNEL_URL",(function(){return _})),n.d(e,"CHANNEL_VIDEOS_BASE_URL",(function(){return m})),n.d(e,"CHANNEL_VIDEOS_URL",(function(){return y})),n.d(e,"CHANNEL_PLAYLIST_URL",(function(){return v})),n.d(e,"CHANNEL_PLAYLIST_PAGE_URL",(function(){return g})),n.d(e,"CHANNEL_PAGE_URL",(function(){return h})),n.d(e,"LIBRARY_URL",(function(){return O})),n.d(e,"LIBRARY_SUBSCRIPTIONS_URL",(function(){return b})),n.d(e,"LIBRARY_LIKED_URL",(function(){return E})),n.d(e,"LIBRARY_WATCHLATER_URL",(function(){return w})),n.d(e,"LIBRARY_HISTORY_URL",(function(){return S})),n.d(e,"LIBRARY_COLLECTIONS_URL",(function(){return A})),n.d(e,"LIBRARY_UPLOADS_URL",(function(){return L})),n.d(e,"LIBRARY_SUBSCRIPTIONS_TOPICS_VIDEOS_URL",(function(){return R})),n.d(e,"LIBRARY_SUBSCRIPTIONS_CHANNELS_VIDEOS_URL",(function(){return I})),n.d(e,"LIBRARY_COLLECTION_URL",(function(){return T})),n.d(e,"WATCHING_URL",(function(){return N})),n.d(e,"WATCHING_PLAYLIST_URL",(function(){return j})),n.d(e,"LOGIN_URL",(function(){return C})),n.d(e,"REGISTER_URL",(function(){return U})),n.d(e,"EXPLORE_URL",(function(){return k})),n.d(e,"NICKNAME_CREATION_URL",(function(){return x})),n.d(e,"SEARCH_URL",(function(){return D})),n.d(e,"SEARCH_QUERY_URL",(function(){return P})),n.d(e,"SEARCH_QUERY_PAGE_URL",(function(){return F})),n.d(e,"SEARCH_VIDEOS_URL",(function(){return B})),n.d(e,"SEARCH_LIVES_URL",(function(){return M})),n.d(e,"SEARCH_CHANNELS_URL",(function(){return H})),n.d(e,"SEARCH_COLLECTIONS_URL",(function(){return G})),n.d(e,"SEARCH_TOPICS_URL",(function(){return V})),n.d(e,"SEARCH_HASHTAGS_URL",(function(){return q})),n.d(e,"FEED_URL",(function(){return K})),n.d(e,"TOPIC_URL",(function(){return z})),n.d(e,"COLLECTION_BASE_URL",(function(){return Y})),n.d(e,"COLLECTION_URL",(function(){return $})),n.d(e,"LEGAL_URL",(function(){return W})),n.d(e,"LEGAL_CONSENT",(function(){return X})),n.d(e,"LEGAL_USPRIVACY",(function(){return Q})),n.d(e,"LEGAL_USPRIVACY_NOTICE",(function(){return J})),n.d(e,"LEGAL_USPRIVACY_FAQ",(function(){return Z})),n.d(e,"SETTINGS_URL",(function(){return tt})),n.d(e,"SETTINGS_URL_EDIT_ACCOUNT",(function(){return et})),n.d(e,"SETTINGS_URL_CHANGE_PASSWORD",(function(){return nt})),n.d(e,"SETTINGS_URL_NOTIFICATIONS",(function(){return rt})),n.d(e,"SETTINGS_URL_FEEDBACKS",(function(){return ot})),n.d(e,"SETTINGS_URL_DELETE_ACCOUNT",(function(){return it})),n.d(e,"SETTINGS_URL_UPLOAD",(function(){return ct})),n.d(e,"PARTNERS_URL",(function(){return at})),n.d(e,"BLACKLIST_METADATA_ROUTES",(function(){return ut})),n.d(e,"FORBIDDEN_URLS",(function(){return st})),n.d(e,"COOKIE",(function(){return ft})),n.d(e,"HASHTAG_URL",(function(){return dt})),n.d(e,"CATEGORY_URL",(function(){return lt}));var r="https://www.dailymotion.com/",o="https://preprod.dailymotion.com/",i="/",c="/notfound",a="/signin/email",u="/register/validation_code",s="/register/activate",f="/register/email_verification",d="/password/recover",l="/password/reset",p="/password/reinforce",_="/:channelName([a-z0-9_\\\\.-]{3,})",m="".concat(_,"/videos"),y="".concat(_,"/videos/:page([1-9]|10)?"),v="".concat(_,"/playlists"),g="".concat(_,"/playlists/:page([1-9]|10)?"),h="".concat(_,"/:channelPage/:page([1-9]|10)?"),O="/library",b="".concat(O,"/subscriptions"),E="".concat(O,"/liked"),w="".concat(O,"/watchlater"),S="".concat(O,"/history"),A="".concat(O,"/playlists"),L="".concat(O,"/videos"),R="".concat(O,"/subscriptions/topics-videos"),I="".concat(O,"/subscriptions/channels-videos"),T="".concat(O,"/playlist/:collectionXid"),N="/video/:xid",j="/video/:xid?playlist=:playlist_xid",C="/signin",U="/signup",k="/:country([a-z]{2})",x="/signin/username",D="/search",P="".concat(D,"/:query"),F="".concat(P,"/:searchPage"),B="".concat(P,"/videos"),M="".concat(P,"/lives"),H="".concat(P,"/channels"),G="".concat(P,"/playlists"),V="".concat(P,"/topics"),q="".concat(P,"/hashtags"),K="/:country([a-z]{2})/feed",z="/:country([a-z]{2})/topic/:topicXid/:page([1-9]|10)?",Y="/playlist/:collectionXid",$="/playlist/:collectionXid/:page([1-9]|10)?",W="https://legal.dailymotion.com/",X="/legal/consent",Q="/legal/usprivacy",J="https://legal.dailymotion.com/en/usprivacynotice/",Z="https://legal.dailymotion.com/en/pifaqs/",tt="/settings",et="".concat(tt,"/account"),nt="".concat(tt,"/change-password"),rt="".concat(tt,"/notifications"),ot="".concat(tt,"/feedbacks"),it="".concat(tt,"/delete-account"),ct="".concat(tt,"/upload"),at="/dm/partner/offers",ut=[c,X,s,f],st=[X],ft="/cookie",dt="/hashtag/:hashtagName/:page([1-9]|10)?",lt="/category/:categoryId/:page([1-9]|10)?"},sDwS:function(t,e,n){"use strict";var r=n("EcEN"),o=n.n(r),i=n("iKNE"),c=n("KVkK"),a=()=>{var t=o()().replaceAll("-","").toUpperCase();return c.a.save(i.m,t,{domain:".dailymotion.com",maxAge:i.n}),t};e.a=()=>{try{return c.a.load(i.m)||a()}catch(t){return console.error("error loading the v1st cookie"),null}}},sXQO:function(t,e,n){"use strict";var r=n("saAs");e.a=()=>r.k?window.__DEVICE_TYPE__:null},saAs:function(t,e,n){"use strict";(function(t){n.d(e,"a",(function(){return r})),n.d(e,"b",(function(){return o})),n.d(e,"i",(function(){return i})),n.d(e,"g",(function(){return c})),n.d(e,"j",(function(){return a})),n.d(e,"k",(function(){return u})),n.d(e,"m",(function(){return s})),n.d(e,"e",(function(){return f})),n.d(e,"l",(function(){return d})),n.d(e,"h",(function(){return l})),n.d(e,"f",(function(){return p})),n.d(e,"c",(function(){return _})),n.d(e,"d",(function(){return m}));var r="f1a362d288c1b98099c7",o="eea605b96e01c796ff369935357eca920c5da4c5",i="1095600231293-ih62cdtmregosipj9cbasor4tpb632mr.apps.googleusercontent.com",c="96937694899",a="6LfetSQUAAAAAD-VJkr8eOrQAiuePX81T9f-dF5k",u="undefined"!=typeof window,s=!u,f=!0,d=f&&!u,l="AIzaSyCNDjPnF1V3Wcdw7-NB9u9pT4yvOTqBnuA",p=!1,_=(u?window.__API_ENDPOINT__:t.env.API_ENDPOINT)||"https://graphql.api.dailymotion.com/",m=(u?window.__AUTH_ENDPOINT__:t.env.AUTH_ENDPOINT)||"https://graphql.api.dailymotion.com/oauth/token"}).call(this,n("8oxB"))},"x/k7":function(t,e,n){"use strict";n.d(e,"a",(function(){return f})),n.d(e,"c",(function(){return d})),n.d(e,"b",(function(){return l}));var r=n("lSNA"),o=n.n(r),i=n("eCGq"),c=n.n(i);function a(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function u(t){for(var e=1;ec.a.get(s),d=()=>{var t,e,n=f(),r=!n||Date.now()>=n.lastAction+18e5?(t=(null==n?void 0:n.number)||0,{firstAction:Date.now(),id:Date.now(),lastAction:Date.now(),number:t+1}):u(u({},n),{},{lastAction:Date.now()});return e=r,c.a.set(s,e),r},l=()=>{c.a.set(s,!1),d()}},xDdU:function(t,e,n){var r=n("4fRq"),o=n("I2ZF"),i=r(),c=[1|i[0],i[1],i[2],i[3],i[4],i[5]],a=16383&(i[6]<<8|i[7]),u=0,s=0;t.exports=function(t,e,n){var r=e&&n||0,i=e||[],f=void 0!==(t=t||{}).clockseq?t.clockseq:a,d=void 0!==t.msecs?t.msecs:(new Date).getTime(),l=void 0!==t.nsecs?t.nsecs:s+1,p=d-u+(l-s)/1e4;if(p<0&&void 0===t.clockseq&&(f=f+1&16383),(p<0||d>u)&&void 0===t.nsecs&&(l=0),l>=1e4)throw new Error("uuid.v1(): Can\'t create more than 10M uuids/sec");u=d,s=l,a=f;var _=(1e4*(268435455&(d+=122192928e5))+l)%4294967296;i[r++]=_>>>24&255,i[r++]=_>>>16&255,i[r++]=_>>>8&255,i[r++]=255&_;var m=d/4294967296*1e4&268435455;i[r++]=m>>>8&255,i[r++]=255&m,i[r++]=m>>>24&15|16,i[r++]=m>>>16&255,i[r++]=f>>>8|128,i[r++]=255&f;for(var y=t.node||c,v=0;v<6;++v)i[r+v]=y[v];return e||o(i)}},xk4V:function(t,e,n){var r=n("4fRq"),o=n("I2ZF");t.exports=function(t,e,n){var i=e&&n||0;"string"==typeof t&&(e="binary"==t?new Array(16):null,t=null);var c=(t=t||{}).random||(t.rng||r)();if(c[6]=15&c[6]|64,c[8]=63&c[8]|128,e)for(var a=0;a<16;++a)e[i+a]=c[a];return e||o(c)}},yLpj:function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},zXnM:function(t,e,n){"use strict";n.d(e,"a",(function(){return d})),n.d(e,"b",(function(){return l}));var r=n("lSNA"),o=n.n(r),i=n("saAs"),c=n("qyIf");function a(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function u(t){for(var e=1;e{var[e,n]=t;return[e.toUpperCase(),n]})))}return{}}()),i.k&&window.__GKS__?window.__GKS__:{}),Object(c.a)(t,s));f=u({},e)}function l(t){if(!f)throw Error("Gatekeepers not initialized");return!0===f[t]}}},[["WgNf",2]]]); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Chats paresseux - Vidéo Dailymotion + + + + + + + + + + + +
+
+
Font
+
+
+ + + + + + + + + + + + + +' +]; diff --git a/tests/cache/www.deviantart.com.art-misty-510056679.php b/tests/cache/www.deviantart.com.art-misty-510056679.php new file mode 100644 index 00000000..b6f7b066 --- /dev/null +++ b/tests/cache/www.deviantart.com.art-misty-510056679.php @@ -0,0 +1,143 @@ + [ + 'server' => [ + 'CloudFront', + 'Apache' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:43 GMT', + 'Mon, 10 Jun 2024 15:58:43 GMT', + 'Mon, 10 Jun 2024 15:58:43 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=ISO-8859-1', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '167', + '0' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://www.deviantart.com/art/Misty-510056679', + 'https://www.deviantart.com/sakimichan/art/Misty-510056679' + ], + 'x-cache' => [ + 'Redirect from cloudfront', + 'Miss from cloudfront', + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 da67d85897eed331d26551a2e5a894dc.cloudfront.net (CloudFront)', + '1.1 46b7282ebe1a484df942bd68bfa2c656.cloudfront.net (CloudFront)', + '1.1 46b7282ebe1a484df942bd68bfa2c656.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD53-P3', + 'MAD53-P3', + 'MAD53-P3' + ], + 'x-amz-cf-id' => [ + '1R7cYZ7XRS6UobE83ZkH3arAZPQHOxQjTEZ04Dd9dS5GcEqWNEmb9g== HTTP/2 301', + '-3iohXjsoQcSit9Dr_vLzwWklIVt1i1p3YR0Eq64eQdVUJ6hogmKTQ== HTTP/2 200', + '-lOhSURM6BtXMSll397RoO9RpQOTcOHnKZESBxYBnW9cKMY9hEY2XQ==' + ], + 'p3p' => [ + 'policyref="/w3c/p3p.xml", CP="NOI DSP COR CURa OUR STP"' + ], + 'set-cookie' => [ + 'userinfo=__e61bc7b0bed91ac45147%3B%7B%22username%22%3A%22%22%2C%22uniqueid%22%3A%22daf182d36b5355fe5fd26f02a598e614%22%2C%22dvs9-1%22%3A1%7D; expires=Wed, 10-Jul-2024 15:58:43 GMT; Max-Age=2592000; path=/; domain=.deviantart.com; SameSite=Lax' + ], + 'x-backend' => [ + 'web_http_back', + 'da_deviation_back' + ], + 'cross-origin-opener-policy' => [ + 'same-origin-allow-popups' + ], + 'origin-agent-cluster' => [ + '?1' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'strict-transport-security' => [ + 'max-age=5184000; includeSubDomains' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-dns-prefetch-control' => [ + 'off' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'x-xss-protection' => [ + '0' + ], + 'content-security-policy' => [ + 'object-src wixmp-ed30a86b8c4ca887773594c2.wixmp.com wixmp-395331243bc2089e8c09c8d3.wixmp.com img-deviantart.wixmp.com;script-src \'nonce-f370d1e865ae17a39bfbc008b18e38be\' \'unsafe-inline\' \'unsafe-eval\' \'strict-dynamic\' https: http: ;base-uri \'none\';frame-ancestors \'self\' sta.sh;upgrade-insecure-requests;block-all-mixed-content' + ], + 'accept-ch' => [ + 'Sec-CH-Viewport-Width, Sec-CH-Viewport-Height' + ], + 'accept-ch-lifetime' => [ + '86400' + ], + 'content-language' => [ + 'en' + ], + 'cache-control' => [ + 'no-cache' + ], + 'da-sr' => [ + 'u' + ], + 'server-timing' => [ + 'p;dur=62.550486981868744, r;dur=16.038680016994476, o;dur=10.433292984962463, t;dur=89.02245998382568' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'br' + ], + 'x-seen-by' => [ + '' + ], + 'Content-Location' => [ + 'https://www.deviantart.com/sakimichan/art/Misty-510056679' + ], + 'X-Request-Time' => [ + '1.027 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Misty by sakimichan on DeviantArt
sakimichan on DeviantArthttps://www.deviantart.com/sakimichan/art/Misty-510056679sakimichan

Deviation Actions

sakimichan's avatar

Misty

By
Published:
386.6K Views1 Collected Privately

Badge Awards

Description

Face Book llOnline Store ll Tumblr ll Help support me on Patreon and get special perks<3llArtstation

I used to watch pokemon when I was younger, and it was  the one with Ash, Brock and misty : ) Good times ! I wanted to draw her in a more anime style ! it was fun adding her pokemons in this piece as well  :D and It was great experimenting with water effects too.

❅ PSD
❅full video process
❅High res jpg for this piece and many others will be made 

 available through my patreon 


Patreon reward archive 
( see what rewards you can get by helping support me !)
Thank you for your interest!

used: photoshop CS6
Image size
695x900px 676.6 KB
© 2015 - 2024 sakimichan
Comments675
Join the community to add your comment. Already a deviant? Log In
GrassTamerBC's avatar

WOW! You managed to pull of realism with an AMAZING facial expression. That is extremely hard to do. Most people give a lifeless “model face” to realistic drawings, but you put so much care into it.

' +]; diff --git a/tests/cache/www.flickr.com.photos-desescribir-sets-72157650686499888.php b/tests/cache/www.flickr.com.photos-desescribir-sets-72157650686499888.php new file mode 100644 index 00000000..0dd39321 --- /dev/null +++ b/tests/cache/www.flickr.com.photos-desescribir-sets-72157650686499888.php @@ -0,0 +1,1509 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:23 GMT' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'cache-control' => [ + 'no-cache, max-age=0, must-revalidate, no-store' + ], + 'pragma' => [ + 'no-cache' + ], + 'x-request-id' => [ + '9f884c77-3dd7-447f-903d-303f09761d7d' + ], + 'set-cookie' => [ + 'xb=355575; Domain=.flickr.com; Path=/; Expires=Tue, 10 Jun 2025 15:59:22 GMT', + 'ccc=%7B%22needsConsent%22%3Atrue%2C%22managed%22%3A0%2C%22changed%22%3A0%2C%22info%22%3A%7B%22cookieBlock%22%3A%7B%22level%22%3A0%2C%22blockRan%22%3A0%7D%7D%2C%22freshServerContext%22%3Atrue%7D; Domain=.flickr.com; Path=/; Expires=Wed, 10 Jul 2024 15:59:22 GMT' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 c95bbb2353ba80a0b30261c24e526ab4.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD56-P4' + ], + 'x-amz-cf-id' => [ + '09qETx9ckKT4WQrysX8F5pxV1ms4Ikk9KEm9_ev9mHSki3zisqWDwQ==' + ], + 'Content-Location' => [ + 'https://www.flickr.com/photos/desescribir/sets/72157650686499888' + ], + 'X-Request-Time' => [ + '0.682 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + Günther Förg. Verfolgen Malerei / Fundación Luís Seoane | Flickr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+
+
+
+
+ + +
+
+
+
+ +
+
+ + +
+
+ Günther Förg. Verfolgen Malerei / Fundación Luís Seoane +
+ + + + +
+
+ + + + +
+ +
+
+ 22 photos + · + 93 views +
+
+ +
+ +
+ + + +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+ + + + + + + + + + + + + +' +]; diff --git a/tests/cache/www.flickr.com.photos-desescribir.php b/tests/cache/www.flickr.com.photos-desescribir.php new file mode 100644 index 00000000..2989fb22 --- /dev/null +++ b/tests/cache/www.flickr.com.photos-desescribir.php @@ -0,0 +1,1191 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:21:53 GMT' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'cache-control' => [ + 'no-cache, max-age=0, must-revalidate, no-store' + ], + 'pragma' => [ + 'no-cache' + ], + 'x-request-id' => [ + '25727e72' + ], + 'set-cookie' => [ + 'xb=101345; Domain=.flickr.com; Path=/; Expires=Mon, 04 Apr 2022 15:21:53 GMT' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 8aa451f83e0a7ce3b7e0bc3b04314535.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD50-C1' + ], + 'x-amz-cf-id' => [ + 't3wbi1qrL5sdpQRZ7y2hrUA_Xz9ij93AcElFCTspBdl7sq1niPNAiw==' + ], + 'Content-Location' => [ + 'https://www.flickr.com/photos/desescribir' + ], + 'X-Request-Time' => [ + '1.317 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + + + + + + + + + + + + + + + + + + + desescribir | Flickr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + new icn messageflickr-free-ic3d pan white +
+
+
+
+ + +

Drag to set position!

+
+
+
+
+ +
+ +
+
+
+
+
+
+
+

+ desescribir +

+ + + + + +
+ + + + +
+ + +
+
+
+
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + + +
+ +
+
+ + +
+
+ + + + + + + + + + + +' +]; diff --git a/tests/cache/www.flickr.com.services-oembed.a0ab60d32d7c7bc81f9e6905cad14c4e.php b/tests/cache/www.flickr.com.services-oembed.a0ab60d32d7c7bc81f9e6905cad14c4e.php new file mode 100644 index 00000000..561f381e --- /dev/null +++ b/tests/cache/www.flickr.com.services-oembed.a0ab60d32d7c7bc81f9e6905cad14c4e.php @@ -0,0 +1,63 @@ + [ + 'content-type' => [ + 'application/json' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:23 GMT' + ], + 'server' => [ + 'Apache/2.4.59 (Ubuntu)' + ], + 'set-cookie' => [ + 'localization=es-us%3Bes%3Bes; expires=Mon, 08-Jun-2026 15:59:23 GMT; Max-Age=62899200; path=/; domain=.flickr.com', + 'flrbp=1718035163-811a4bc56c359ff712aa8e2ff57320f1f8eef723; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrbgrp=1718035163-7aa49fbf74ff760b5a837d9fba1ce177cd63c9eb; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrbgdrp=1718035163-1176e4f6311d506c44573fcdf026a4fb601ce269; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrbgmrp=1718035163-6e89381ca16d14852bb382b46b48a929db11bc0c; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrbrst=1718035163-9cf7efbc7c5a1241f7eac70a42ca10fbf5c106f3; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrtags=1718035163-f2588f13bcd0eba8ab21e0a0fa8f17d4ad7f4d19; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrbrp=1718035163-9900fbf114cb5d89c9df03ee4f52b95da669ac5f; expires=Sat, 07-Dec-2024 15:59:23 GMT; Max-Age=15552000; path=/; domain=.flickr.com; HttpOnly', + 'flrb=28; expires=Mon, 10-Jun-2024 17:59:23 GMT; Max-Age=7200; path=/; domain=.flickr.com; HttpOnly', + 'ccc=%7B%22needsConsent%22%3Atrue%2C%22managed%22%3A0%2C%22changed%22%3A0%2C%22info%22%3A%7B%22cookieBlock%22%3A%7B%22level%22%3A0%2C%22blockRan%22%3A0%7D%7D%2C%22freshServerContext%22%3Atrue%7D; expires=Wed, 10-Jul-2024 15:59:23 GMT; Max-Age=2592000; path=/; domain=.flickr.com', + 'ccc=%7B%22needsConsent%22%3Atrue%2C%22managed%22%3A0%2C%22changed%22%3A0%2C%22info%22%3A%7B%22cookieBlock%22%3A%7B%22level%22%3A0%2C%22blockRan%22%3A1%7D%7D%2C%22freshServerContext%22%3Atrue%7D; expires=Wed, 10-Jul-2024 15:59:23 GMT; Max-Age=2592000; path=/; domain=.flickr.com' + ], + 'content-security-policy' => [ + 'style-src \'unsafe-inline\' https://*.flickr.com https://*.staticflickr.com https://*.flickr.net https://*.braintreegateway.com https://*.kaptcha.com https://*.paypal.com http://api.flickr.com https://*.pinterest.com https://connect.facebook.net https://*.facebook.com https://*.maps.api.here.com https://*.maps.cit.api.here.com https://cdn.siftscience.com https://trustarc.mgr.consensu.org/ https://*.trustarc.com; default-src \'unsafe-inline\' https://*.flickr.com https://*.staticflickr.com https://*.flickr.net https://*.braintreegateway.com https://*.kaptcha.com https://*.paypal.com http://api.flickr.com https://*.pinterest.com https://connect.facebook.net https://*.facebook.com https://*.maps.api.here.com https://*.maps.cit.api.here.com https://cdn.siftscience.com https://trustarc.mgr.consensu.org/ https://*.trustarc.com; img-src data: blob: https://*.flickr.com https://*.flickr.net http://*.flickr.net https://*.staticflickr.com http://*.staticflickr.com https://*.yimg.com https://*.yahoo.com https://image.maps.api.here.com https://*.paypal.com https://*.pinterest.com http://*.static-alpha.flickr.com https://connect.facebook.net https://*.facebook.com https://*.maps.api.here.com https://*.maps.cit.api.here.com https://creativecommons.org https://hexagon-analytics.com https://api.mapbox.com https://*.trustarc.com; script-src \'unsafe-eval\' \'unsafe-inline\' https://*.flickr.com http://*.flickr.net https://*.flickr.net https://*.staticflickr.com https://*.analytics.yahoo.com https://yep.video.yahoo.com https://video.media.yql.yahoo.com https://*.yahooapis.com https://*.braintreegateway.com https://*.paypalobjects.com https://connect.facebook.net https://*.facebook.com https://*.maps.api.here.com https://*.maps.cit.api.here.com https://cdn.siftscience.com https://consent.trustarc.com https://trustarc.mgr.consensu.org; connect-src https://*.flickr.com https://*.flickr.net http://*.flickr.net https://*.staticflickr.com https://geo.query.yahoo.com https://*.yahooapis.com http://api.flickr.com https://*.pinterest.com http://*.yahoo.com https://*.maps.api.here.com https://*.maps.cit.api.here.com https://cdn.siftscience.com https://*.trustarc.com https://com-flickr-prod1.mini.snplow.net https://maps.flickr.com;' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'content-encoding' => [ + 'gzip' + ], + 'x-cache' => [ + 'Miss from cloudfront' + ], + 'via' => [ + '1.1 0bfc6b87e9420bc059d4e18edfb7571c.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD56-P4' + ], + 'x-amz-cf-id' => [ + '6-0PTnwCFKpk2lttWA8iN-dsmLWAZGxTeHVHNbtogmN2Ws7zsiC0YA==' + ], + 'Content-Location' => [ + 'https://www.flickr.com/services/oembed/?format=json&url=https%3A%2F%2Fwww.flickr.com%2Fphotos%2Fdesescribir%2Fsets%2F72157650686499888' + ], + 'X-Request-Time' => [ + '0.218 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"rich","flickr_type":"album","title":"G\\u00fcnther F\\u00f6rg. Verfolgen Malerei \\/ Fundaci\\u00f3n Lu\\u00eds Seoane","author_name":"desescribir","author_url":"https:\\/\\/www.flickr.com\\/photos\\/desescribir\\/","width":800,"height":600,"web_page":"https:\\/\\/www.flickr.com\\/photos\\/desescribir\\/sets\\/72157650686499888","thumbnail_url":"https:\\/\\/live.staticflickr.com\\/8572\\/16055522574_ce77fde14e_b.jpg","thumbnail_width":800,"thumbnail_height":600,"web_page_short_url":"https:\\/\\/flic.kr\\/s\\/aHsk8hUbqq","license_url":"https:\\/\\/creativecommons.org\\/licenses\\/by-nc-nd\\/2.0\\/","html":"\'G\\u00fcnther<\\/a>Antes de ir a Google Maps
Google

Antes de ir a Google

Usamos cookies y datos para:

  • Proporcionar y mantener nuestros servicios
  • Hacer un seguimiento de las interrupciones y prevenir el spam, el fraude y los abusos
  • Medir la interacción de la audiencia y estadísticas de los sitios para entender cómo se utilizan nuestros servicios y mejorar su calidad

Si eliges Aceptar todo, también usaremos cookies y datos para:

  • Desarrollar y mejorar nuevos servicios
  • Proporcionar anuncios y medir su eficacia
  • Mostrar contenido personalizado en función de tus ajustes
  • Mostrar anuncios personalizados en función de tus ajustes

Si eliges Rechazar todo, no usaremos cookies para estos fines adicionales.

El contenido no personalizado está influido por factores como lo que estés viendo en ese momento, la actividad de tu sesión de búsqueda activa y tu ubicación. Los anuncios no personalizados están influidos por lo que estés viendo en ese momento y tu ubicación general. El contenido y los anuncios personalizados también pueden incluir resultados y recomendaciones más relevantes, así como anuncios basados en la actividad que se haya realizado previamente con este navegador, como búsquedas en Google anteriores. En caso necesario, también usamos cookies y datos para adaptar la experiencia de modo que sea apropiada para determinada edad.

Selecciona Más opciones para ver información adicional, como detalles sobre la gestión de la configuración de privacidad. También puedes visitar g.co/privacytools/es en cualquier momento.

' +]; diff --git a/tests/cache/www.hookem.com.story-texas-shortstop-joe-baker-arrested-public-intoxication.php b/tests/cache/www.hookem.com.story-texas-shortstop-joe-baker-arrested-public-intoxication.php new file mode 100644 index 00000000..3bf921a2 --- /dev/null +++ b/tests/cache/www.hookem.com.story-texas-shortstop-joe-baker-arrested-public-intoxication.php @@ -0,0 +1,141 @@ + [ + 'connection' => [ + 'close' + ], + 'content-length' => [ + '0', + '0 HTTP/2 302', + '0 HTTP/2 404', + '548' + ], + 'retry-after' => [ + '0', + '0', + '0' + ], + 'location' => [ + 'https://www.hookem.com/story/texas-shortstop-joe-baker-arrested-public-intoxication/', + 'https://eu.hookem.com/story/texas-shortstop-joe-baker-arrested-public-intoxication/', + 'https://eu.hookem.com/' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes', + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:47 GMT', + 'Mon, 10 Jun 2024 15:58:47 GMT', + 'Mon, 10 Jun 2024 15:58:47 GMT', + 'Mon, 10 Jun 2024 15:58:47 GMT' + ], + 'nel' => [ + '{"report_to":"default","max_age":31557600,"include_subdomains":true,"success_fraction":0.005}', + '{"report_to":"default","max_age":31557600,"include_subdomains":true,"success_fraction":0.005}' + ], + 'report-to' => [ + '{"max_age":31557600,"include_subdomains":true,"endpoints":[{"url":"https://reporting-api.gannettinnovation.com/"}]}', + '{"max_age":31557600,"include_subdomains":true,"endpoints":[{"url":"https://reporting-api.gannettinnovation.com/"}]}' + ], + 'x-cache' => [ + 'HIT', + 'HIT', + 'HIT, HIT', + 'HIT, HIT' + ], + 'vary' => [ + 'User-Agent', + 'User-Agent', + 'Accept-Encoding' + ], + 'cache-control' => [ + 'max-age=300,private HTTP/2 302', + 'max-age=300,private', + 'max-age=10', + 'max-age=10' + ], + 'set-cookie' => [ + 'gnt_eid=(null);domain=.hookem.com;path=/;secure;samesite=lax;max-age=5184000;priority=high;', + 'gnt_i=69894212976833900198*12430*ES~C;domain=.hookem.com;path=/;samesite=lax;secure;priority=high;', + 'gup_clientid=0; domain=eu.hookem.com; max-age=-1; path=/; secure', + 'gup_clientid=0; domain=hookem.com; max-age=-1; path=/; secure', + 'gup_anonid=0; domain=hookem.com; max-age=-1; path=/; secure', + 'gup_lng=0; domain=hookem.com; max-age=-1; path=/; secure' + ], + 'content-security-policy' => [ + 'upgrade-insecure-requests', + 'upgrade-insecure-requests', + 'upgrade-insecure-requests' + ], + 'strict-transport-security' => [ + 'max-age=63072000;includeSubDomains;preload', + 'max-age=600', + 'max-age=600' + ], + 'server' => [ + 'Varnish' + ], + 'via' => [ + '1.1 varnish, 1.1 varnish', + '1.1 varnish, 1.1 varnish' + ], + 'x-robots-tag' => [ + 'noindex, nofollow', + 'noindex, nofollow' + ], + 'gannett-debug-path' => [ + 'region: east', + 'region: west ---> region: east' + ], + 'gannett-debug-path-full' => [ + 'restarts: 0 ttl: 1200.000 shield: false server: cache-mad2200136-MAD path: region: east', + 'restarts: 0 ttl: 1200.000 shield: false server: cache-mad22073-MAD path: region: east >>>> restarts: 0 ttl: 1200.000 shield: true server: cache-fra-eddf8230088-FRA path: region: west ---> region: east' + ], + 'age' => [ + '90', + '15356' + ], + 'x-served-by' => [ + 'cache-fra-etou8220056-FRA, cache-mad2200133-MAD', + 'cache-fra-eddf8230105-FRA, cache-mad2200133-MAD' + ], + 'x-cache-hits' => [ + '0, 0', + '1, 0' + ], + 'x-timer' => [ + 'S1718035128.698632,VS0,VE2', + 'S1718035128.716499,VS0,VE1' + ], + 'content-type' => [ + 'text/html' + ], + 'Content-Location' => [ + 'https://eu.hookem.com/' + ], + 'X-Request-Time' => [ + '0.195 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => ' +404 Not Found + +

404 Not Found

+
nginx
+ + + + + + + + +' +]; diff --git a/tests/cache/www.itmedia.co.jp.news-articles-2410-28-news159.html.php b/tests/cache/www.itmedia.co.jp.news-articles-2410-28-news159.html.php new file mode 100644 index 00000000..bac05c90 --- /dev/null +++ b/tests/cache/www.itmedia.co.jp.news-articles-2410-28-news159.html.php @@ -0,0 +1,2019 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +さくらインターネット、営業利益が前年同期比420%増 GPUクラウド伸長で“生成AIフィーバー”? 上期決算 - ITmedia NEWS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + +
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
メディア
+
+
+
+
+ + + +
+ +
+
+
+
+ + +
+ +
+ + +
+
+
+ +ITmedia NEWS > + +速報 > + + + +
+
+
+ +
+ +
+
+ + + +
+ + + + +
ITmedia AI+ AI活用のいまが分かる
+ + + + + + + + + + + + + +
+

さくらインターネット、営業利益が前年同期比420%増 GPUクラウド伸長で“生成AIフィーバー”? 上期決算

+
+ + + + + + + + + +
» 2024年10月28日 17時55分 公開
+
[ITmedia]
+ + +
+ + + + + +
+ + + + + + +
+ +
+
+
+ +
+ + + + + +
+
+ + + + + + +

 さくらインターネットは10月28日、2025年3月期第2四半期累計(24年4月〜9月)の連結決算を発表した。売上高は132億7100万円(前年同期比28.3%増)、営業利益は12億9500万円(同419.4%増)だった。生成AI需要によってGPUクラウドサービスが伸長したという。

+ +
photo +さくらインターネットの決算説明資料
+ +

 GPUクラウドサービス単体の売上高も明らかに。期間中に約20億1849万円を売り上げたという。さらに、86億9000万円かけてGPUを追加調達する方針も示した。4月に調達を発表した「NVIDIA HGX B200」の納品が遅れるため、「NVIDIA H200」1072基を84億3000万円で、「H100」40基を2億6000万円で調達するという。H200は25年2月以降、H100は24年12月末から25年1月の間にサービス提供での利用を始める。

+ +
photo +GPUの追加調達計画(さくらインターネット 「GPUクラウドサービスへの追加投資に関するお知らせ」から引用)
+ +

 日本政府が共通クラウド基盤「ガバメントクラウド」として採択したクラウドサービス「さくらのクラウド」についても開発計画の進捗を発表した。同サービスは2025年3月までに要件を満たす条件での採択が決まっており、同社は進捗について「順調に前進」とした。

+ + + + + + + + + + + +

Copyright © ITmedia, Inc. All Rights Reserved.

+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+
+
+ +
+
+ +
+ + + + +
+ + + + +
+ + + + + + + + +
+
+
+
+
+
+
+ +
+ + + +
+ + +
+ + + + + + + +
+ + + + + + +
+ + +
+ + + + + + +
+
+ +
+
+ + + + + + + + + +
+
+ +
+ + + + + +
+
+
+
+ +
+
+
+ +
+ + + + + + + + +
+
+ +
+ + +
+ + +
+
+ + + + + + +
+ +
+ + + +
+
+
+
+
+ + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TESTHTML; + +return [ + 'headers' => [ + 'content-type' => [ + 'text/html', + ], + 'cache-control' => [ + 'max-age=900', + ], + 'expires' => [ + 'Sun, 03 Nov 2024 04:03:10 GMT', + ], + 'date' => [ + 'Sun, 03 Nov 2024 03:48:10 GMT', + ], + 'server' => [ + 'nginx', + ], + 'strict-transport-security' => [ + 'max-age=31536000', + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-encoding' => [ + 'gzip' + ], + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => $body, +]; diff --git a/tests/cache/www.kickstarter.com.projects-1452363698-good-seed-craft-veggie-burgers.php b/tests/cache/www.kickstarter.com.projects-1452363698-good-seed-craft-veggie-burgers.php new file mode 100644 index 00000000..ffe42154 --- /dev/null +++ b/tests/cache/www.kickstarter.com.projects-1452363698-good-seed-craft-veggie-burgers.php @@ -0,0 +1,79 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:49 GMT' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'critical-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'cross-origin-embedder-policy' => [ + 'require-corp' + ], + 'cross-origin-opener-policy' => [ + 'same-origin' + ], + 'cross-origin-resource-policy' => [ + 'same-origin' + ], + 'origin-agent-cluster' => [ + '?1' + ], + 'permissions-policy' => [ + 'accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()' + ], + 'referrer-policy' => [ + 'same-origin' + ], + 'x-content-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'cf-mitigated' => [ + 'challenge' + ], + 'cf-chl-out' => [ + 'uHJaPzvaJgaqJ0C5iHPCyxbEeWY/SU95iVSNoU3Ox36Td97+xaf21soVLiBZzPrsknbBv6Oo0PjYYtPqv2I+PdxDvWE+BvDDggCAwiv87QZf2VsBRTYD2DpgffA10ixvkTn/gefG/MgYu9VmvS9ZBg==$U3vEx0k0Mpa1+A6klkYRiA==' + ], + 'cache-control' => [ + 'private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ], + 'expires' => [ + 'Thu, 01 Jan 1970 00:00:01 GMT' + ], + 'set-cookie' => [ + '__cf_bm=P8dEBErXbWS5GXMsJ0T.Y4Da6ihrH7L_EoyGgeVFRpM-1718035129-1.0.1.1-4X9LoyACnb1eZlbsK5yhrDc1yiZE3LmYQWUvGkZcNLXEe4uJ604lT3UHkWDc.mzxUlXXP2KvG.Lqlp0yBzH4nQ; path=/; expires=Mon, 10-Jun-24 16:28:49 GMT; domain=.kickstarter.com; HttpOnly; Secure; SameSite=None' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare' + ], + 'cf-ray' => [ + '891a90a84a8a1bb7-MAD' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://www.kickstarter.com/projects/1452363698/good-seed-craft-veggie-burgers' + ], + 'X-Request-Time' => [ + '0.104 ms' + ] + ], + 'statusCode' => 403, + 'reasonPhrase' => 'Forbidden', + 'body' => 'Just a moment...
' +]; diff --git a/tests/cache/www.kickstarter.com.services-oembed.ea62eb3c242348e8741cc9488b318f0e.php b/tests/cache/www.kickstarter.com.services-oembed.ea62eb3c242348e8741cc9488b318f0e.php new file mode 100644 index 00000000..3b39a4cf --- /dev/null +++ b/tests/cache/www.kickstarter.com.services-oembed.ea62eb3c242348e8741cc9488b318f0e.php @@ -0,0 +1,95 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:49 GMT', + 'Mon, 10 Jun 2024 15:58:49 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=UTF-8' + ], + 'content-length' => [ + '167' + ], + 'connection' => [ + 'keep-alive' + ], + 'cache-control' => [ + 'max-age=3600', + 'private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:58:49 GMT', + 'Thu, 01 Jan 1970 00:00:01 GMT' + ], + 'location' => [ + 'https://www.kickstarter.com/services/oembed?url=https%3A%2F%2Fwww.kickstarter.com%2Fprojects%2F1452363698%2Fgood-seed-craft-veggie-burgers&format=json' + ], + 'set-cookie' => [ + '__cf_bm=KVhOCLoxDqCqLZ7SXop0QY2J2q3_ugkVeOzKiiufFQc-1718035129-1.0.1.1-nWbSu2ifvqRTjS0RFsaRGT68t0YTu.3WPeBRfZC.SKOql3yUjEvFIj_2Ij0JXpeo6WY_xdYu0y55M_owHRdfOg; path=/; expires=Mon, 10-Jun-24 16:28:49 GMT; domain=.kickstarter.com; HttpOnly' + ], + 'vary' => [ + 'Accept-Encoding', + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a90a8df63041e-MAD HTTP/2 403', + '891a90a94fc33845-MAD' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'critical-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'cross-origin-embedder-policy' => [ + 'require-corp' + ], + 'cross-origin-opener-policy' => [ + 'same-origin' + ], + 'cross-origin-resource-policy' => [ + 'same-origin' + ], + 'origin-agent-cluster' => [ + '?1' + ], + 'permissions-policy' => [ + 'accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()' + ], + 'referrer-policy' => [ + 'same-origin' + ], + 'x-content-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'cf-mitigated' => [ + 'challenge' + ], + 'cf-chl-out' => [ + 'y0Ycc5OrMNR807dZ4zEWmJ8tmVmYKuRgvO2l6y/Jixl+3hZE+8vR3b2MJlHKpmcKHvYq5jxHLznOZ5PtT0wF+fOYp6J6ptx5iwDl/Z0TUQiQh55sFYUkM1PuNE8veI+kB3eumB6pTjwAwFR0vArnWw==$QMimOoSsq0UYc9QrpgIp5Q==' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://www.kickstarter.com/services/oembed?url=https%3A%2F%2Fwww.kickstarter.com%2Fprojects%2F1452363698%2Fgood-seed-craft-veggie-burgers&format=json' + ], + 'X-Request-Time' => [ + '0.123 ms' + ] + ], + 'statusCode' => 403, + 'reasonPhrase' => 'Forbidden', + 'body' => 'Just a moment...
' +]; diff --git a/tests/cache/www.meetup.com.es-gpul-labs-events-248885422.php b/tests/cache/www.meetup.com.es-gpul-labs-events-248885422.php new file mode 100644 index 00000000..24b0b4eb --- /dev/null +++ b/tests/cache/www.meetup.com.es-gpul-labs-events-248885422.php @@ -0,0 +1,99 @@ + [ + 'location' => [ + 'https://www.meetup.com/login/?returnUri=https%3A%2F%2Fwww.meetup.com%2Fgpul-labs%2Fevents%2F248885422%2F' + ], + 'etag' => [ + 'W/"orFoHpwmuQ0LB8Qn3DVgaTN0tGs-q5ti"', + 'W/"mApJ6scbIOa2ztq2L_ll9lL32b3xHMK9"' + ], + 'x-ttl' => [ + '86400.000', + '300.000' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:18 GMT', + 'Mon, 10 Jun 2024 15:59:18 GMT' + ], + 'age' => [ + '0', + '83' + ], + 'x-cache' => [ + 'MISS', + 'MISS, HIT' + ], + 'x-cache-hits' => [ + '0', + '0, 0' + ], + 'set-cookie' => [ + 'MEETUP_BROWSER_ID=id=7e749fa8-535c-4873-b49d-cb9093ac1b85; expires=Sun, 05 Jun 2044 15:59:18 GMT; path=/; domain=.meetup.com; SameSite=None; Secure', + 'MEETUP_TRACK=id=ff48ab1b-7e05-47d1-90e1-df1c07ce4dc7; expires=Sun, 05 Jun 2044 15:59:18 GMT; path=/; domain=.meetup.com; SameSite=None; Secure', + 'SIFT_SESSION_ID=e78fe02b-9df0-45ad-a3ee-b9fa7c9d688c; expires=Mon, 10 Jun 2024 19:59:18 GMT; path=/; domain=.meetup.com; SameSite=Strict; Secure' + ], + 'surrogate-control' => [ + 'public, max-age=86400, stale-while-revalidate=60, stale-if-error=43200' + ], + 'cache-control' => [ + 'no-cache, max-age=0', + 'public, max-age=3600, stale-while-revalidate=60, stale-if-error=43200' + ], + 'content-security-policy' => [ + 'base-uri \'self\'; connect-src * blob: data: *.crazyegg.com ; default-src \'self\' *.meetup.com *.dev.meetup.com:8001 www.sjwoe.com *.crazyegg.com blob: ; font-src * data:; frame-ancestors \'self\'; frame-src *; img-src * data: blob: *.crazyegg.com ;media-src *.meetup.com *.dev.meetup.com:8001 https://secure.meetupstatic.com www.sjwoe.com *.sendbird.com https://sendbird-us-3.s3.amazonaws.com; script-src * \'unsafe-eval\' \'unsafe-inline\' *.crazyegg.com; style-src * \'unsafe-inline\' *.crazyegg.com ; object-src \'none\'', + 'base-uri \'self\'; connect-src * blob: data: *.crazyegg.com ; default-src \'self\' *.meetup.com *.dev.meetup.com:8001 www.sjwoe.com *.crazyegg.com blob: ; font-src * data:; frame-ancestors \'self\'; frame-src *; img-src * data: blob: *.crazyegg.com ;media-src *.meetup.com *.dev.meetup.com:8001 https://secure.meetupstatic.com www.sjwoe.com *.sendbird.com https://sendbird-us-3.s3.amazonaws.com; script-src * \'unsafe-eval\' \'unsafe-inline\' *.crazyegg.com; style-src * \'unsafe-inline\' *.crazyegg.com ; object-src \'none\'' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block', + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'content-type' => [ + 'text/html; charset=utf-8', + 'text/html; charset=utf-8' + ], + 'strict-transport-security' => [ + 'max-age=7776000', + 'max-age=7776000' + ], + 'content-length' => [ + '0 HTTP/2 200', + '10983' + ], + 'cross-origin-opener-policy' => [ + 'same-origin' + ], + 'x-nextjs-cache' => [ + 'HIT' + ], + 'content-encoding' => [ + 'gzip' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'Content-Location' => [ + 'https://www.meetup.com/login/?returnUri=https%3A%2F%2Fwww.meetup.com%2Fgpul-labs%2Fevents%2F248885422%2F' + ], + 'X-Request-Time' => [ + '0.975 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Login to Meetup | Meetup' +]; diff --git a/tests/cache/www.pinterest.com.oembed.json.646222621b58c69c710ef544c8fd86f8.php b/tests/cache/www.pinterest.com.oembed.json.646222621b58c69c710ef544c8fd86f8.php new file mode 100644 index 00000000..528bf25f --- /dev/null +++ b/tests/cache/www.pinterest.com.oembed.json.646222621b58c69c710ef544c8fd86f8.php @@ -0,0 +1,85 @@ + [ + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains; preload' + ], + 'x-ua-compatible' => [ + 'IE=edge' + ], + 'reporting-endpoints' => [ + 'coop-endpoint="https://www.pinterest.com/_/_/coop_report/", coep-endpoint="https://www.pinterest.com/_/_/coep_report/"' + ], + 'cross-origin-opener-policy-report-only' => [ + 'same-origin; report-to="coop-endpoint"' + ], + 'content-security-policy' => [ + 'default-src \'self\' blob: s.pinimg.com; font-src \'self\' s.pinimg.com data: fonts.googleapis.com fonts.gstatic.com use.typekit.net; style-src \'self\' blob: \'unsafe-inline\' data: *.pinimg.com *.pinterest.com accounts.google.com fonts.googleapis.com *.adyen.com *.adyenpayments.com; img-src blob: data: *; base-uri \'none\'; connect-src \'self\' blob: *.pinimg.com *.pinterest.com accounts.google.com *.adyen.com pinterest-salvador.s3.amazonaws.com *.adyenpayments.com *.facebook.com www.googleapis.com *.dropboxapi.com pinterest-aberdeen.s3.amazonaws.com pinterest-aberdeen.s3.us-east-1.amazonaws.com pinterest-anaheim.s3.amazonaws.com pinterest-anaheim.s3.us-east-1.amazonaws.com pinterest-hilo.s3.amazonaws.com pinterest-hilo.s3.us-east-1.amazonaws.com pinterest-sim-toontown.s3.amazonaws.com pinterest-sim-toontown.s3.us-east-1.amazonaws.com pinterest-media-upload.s3.amazonaws.com pinterest-media-upload.s3.us-east-1.amazonaws.com pinterest-media-upload.s3-accelerate.amazonaws.com pinterest-media-upload.s3-accelerate.us-east-1.amazonaws.com pinterest-milwaukee.s3.amazonaws.com pinterest-milwaukee.s3.us-east-1.amazonaws.com pinterest-poughkeepsie.s3.amazonaws.com pinterest-poughkeepsie.s3.us-east-1.amazonaws.com pinterest-waterloo.s3.amazonaws.com pinterest-waterloo.s3.us-east-1.amazonaws.com pinterest-plymouth.s3.amazonaws.com pinterest-plymouth.s3.us-east-1.amazonaws.com pinterest-salvador.s3.us-east-1.amazonaws.com pinterest-yamagata.s3.amazonaws.com pinterest-yamagata.s3.us-east-1.amazonaws.com *.cedexis.com *.cedexis-radar.net *.tvpixel.com api.pinadmin.com *.live-video.net https://*.daily.co https://*.pluot.blue wss://*.wss.daily.co; form-action \'self\' *.adyen.com *.sofort.com *.tink.com *.adyenpayments.com; frame-src \'self\' *.pinimg.com *.pinterest.com *.adyen.com static-sandbox.dlocal.com static.dlocal.com *.google.com *.facebook.com www.recaptcha.net pinterest-hilo.s3.amazonaws.com pinterest-hilo.s3.us-east-1.amazonaws.com pinterest-sim-toontown.s3.amazonaws.com pinterest-sim-toontown.s3.us-east-1.amazonaws.com pinterest-milwaukee.s3.amazonaws.com pinterest-milwaukee.s3.us-east-1.amazonaws.com pinterest-waterloo.s3.amazonaws.com pinterest-waterloo.s3.us-east-1.amazonaws.com pinterest-tolu.s3.amazonaws.com *.pinterdev.com content.googleapis.com *.youtube.com *.youtube-nocookie.com *.ytimg.com player.vimeo.com calendly.com vine.co bid.g.doubleclick.net *.fls.doubleclick.net pinlogs.s3.amazonaws.com pinlogs.s3.us-east-1.amazonaws.com advertising-delivery-metric-reports.s3.amazonaws.com advertising-delivery-metric-reports.s3.us-east-1.amazonaws.com servedby.flashtalking.com pinterest-uk.admo.tv pinterest-uk-web.admo.tv fbrpc://call *.linkedin.com px.ads.linkedin.com; media-src \'self\' blob: data: *.pinimg.com *.live-video.net; object-src \'self\'; script-src \'nonce-41f84319db0cb238dc162c36c80c3212\' \'strict-dynamic\' \'self\' blob: \'unsafe-inline\' *.pinimg.com *.pinterest.com *.adyen.com js.dlocal.com js-sandbox.dlocal.com static-sandbox.dlocal.com static.dlocal.com *.adyenpayments.com \'report-sample\' *.google.com connect.facebook.net *.google-analytics.com *.facebook.com *.googleadservices.com *.doubleclick.net *.googletagmanager.com radar.cedexis.com *.cedexis-test.com www.gstatic.com/recaptcha/ www.gstatic.cn/recaptcha/ www.recaptcha.net \'wasm-unsafe-eval\'; worker-src \'self\' blob: \'unsafe-inline\'; report-uri /_/_/csp_report/?rid=1253678817280813; frame-ancestors \'self\' , script-src \'self\' blob: \'unsafe-inline\' *.pinimg.com *.pinterest.com *.adyen.com js.dlocal.com js-sandbox.dlocal.com static-sandbox.dlocal.com static.dlocal.com *.adyenpayments.com \'report-sample\' *.google.com connect.facebook.net *.google-analytics.com *.facebook.com *.googleadservices.com *.doubleclick.net *.googletagmanager.com radar.cedexis.com *.cedexis-test.com www.gstatic.com/recaptcha/ www.gstatic.cn/recaptcha/ www.recaptcha.net \'wasm-unsafe-eval\'; report-uri /_/_/csp_report/?rid=1253678817280813' + ], + 'content-security-policy-report-only' => [ + 'img-src \'self\' blob: data: *.pinimg.com *.pinterest.com *.google.com *.facebook.com *.cedexis.com *.cedexis-test.com *.citrix.com *.tvpixel.com; report-uri /_/_/csp_report/?reportonly' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'origin-trial' => [ + 'AvlUIFJouPpJAKljRGh7EnYm2Brnx/eu51h39Z7p11vbzNlw2YhkUhxvxZdkS709VlGGNw4Gcg/a9mAzHDrEcQ0AAAB5eyJvcmlnaW4iOiJodHRwczovL3BpbnRlcmVzdC5jb206NDQzIiwiZmVhdHVyZSI6IlNlbmRGdWxsVXNlckFnZW50QWZ0ZXJSZWR1Y3Rpb24iLCJleHBpcnkiOjE2ODQ4ODYzOTksImlzU3ViZG9tYWluIjp0cnVlfQ==' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Full,Sec-CH-UA-Full-Version-List,Sec-CH-UA-Model,Sec-CH-UA-Platform-Version' + ], + 'cache-control' => [ + 'max-age=259200' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'x-envoy-upstream-service-time' => [ + '126' + ], + 'referrer-policy' => [ + 'origin' + ], + 'x-pinterest-rid' => [ + '1253678817280813' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:19 GMT' + ], + 'vary' => [ + 'User-Agent, Accept-Encoding' + ], + 'x-cdn' => [ + 'fastly' + ], + 'alt-svc' => [ + 'h3=":443";ma=600' + ], + 'pinterest-generated-by' => [ + 'coreapp-webapp-prod-0a011986' + ], + 'pinterest-version' => [ + 'f8146f7' + ], + 'content-length' => [ + '550' + ], + 'Content-Location' => [ + 'https://www.pinterest.com/oembed.json?url=https%3A%2F%2Fwww.pinterest.com%2Fpin%2F106890191127977979%2F&format=json' + ], + 'X-Request-Time' => [ + '0.319 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"rich","provider_name":"Pinterest","provider_url":"https://www.pinterest.com/","width":450,"height":663,"title":"Pourparler","author_name":"Leslie Carruthers","author_url":"https://www.pinterest.com/thesearchguru/","html":"","thumbnail_url":"https://i.pinimg.com/236x/b5/34/13/b53413787f3a42c8b9d5b08a6fbb2124.jpg","thumbnail_width":236,"thumbnail_height":295}' +]; diff --git a/tests/cache/www.pinterest.com.pin-106890191127977979.php b/tests/cache/www.pinterest.com.pin-106890191127977979.php new file mode 100644 index 00000000..aca4457d --- /dev/null +++ b/tests/cache/www.pinterest.com.pin-106890191127977979.php @@ -0,0 +1,769 @@ + [ + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains; preload' + ], + 'x-ua-compatible' => [ + 'IE=edge' + ], + 'reporting-endpoints' => [ + 'coop-endpoint="https://www.pinterest.com/_/_/coop_report/", coep-endpoint="https://www.pinterest.com/_/_/coep_report/"' + ], + 'cross-origin-opener-policy-report-only' => [ + 'same-origin; report-to="coop-endpoint"' + ], + 'set-cookie' => [ + 'csrftoken=6d35443ba18175d015c05222341fd3e2; path=/; expires=Tue, 10 Jun 2025 15:59:18 GMT; samesite=lax; secure', + '_pinterest_sess=TWc9PSZlbmIrMTZNaXpBRFpaNkhTMGpDNW1Oc2Y5UkYzYWYrZUoyT0FFQzdUWHprcFhnN1JRbUc4UFVacmtaUXBFTndkRW16dVhReHBvVVJsRUNDYnlocW5nMFJBTlg1UEdxUEdPaml6VEx2dnc0QT0mZkRpVk5wc0tJSUF5NFBUd01OMjYwd3ExbHZJPQ==; path=/; expires=Thu, 05 Jun 2025 15:59:18 GMT; domain=.pinterest.com; samesite=none; secure; httponly', + '_auth=0; path=/; expires=Thu, 05 Jun 2025 15:59:18 GMT; domain=.pinterest.com; secure; httponly', + '_routing_id="234b4ee8-a866-4038-9faa-03883172971a"; Max-Age=86400; Path=/; HttpOnly' + ], + 'p3p' => [ + 'CP="This is not a P3P policy. See https://www.pinterest.com/_/_/help/articles/pinterest-and-p3p for more info."' + ], + 'content-security-policy' => [ + 'default-src \'self\' blob: s.pinimg.com; font-src \'self\' s.pinimg.com data: fonts.googleapis.com fonts.gstatic.com use.typekit.net; style-src \'self\' blob: \'unsafe-inline\' data: *.pinimg.com *.pinterest.com accounts.google.com fonts.googleapis.com *.adyen.com *.adyenpayments.com; img-src blob: data: *; base-uri \'none\'; connect-src \'self\' blob: *.pinimg.com *.pinterest.com accounts.google.com *.adyen.com pinterest-salvador.s3.amazonaws.com *.adyenpayments.com *.facebook.com www.googleapis.com *.dropboxapi.com pinterest-aberdeen.s3.amazonaws.com pinterest-aberdeen.s3.us-east-1.amazonaws.com pinterest-anaheim.s3.amazonaws.com pinterest-anaheim.s3.us-east-1.amazonaws.com pinterest-hilo.s3.amazonaws.com pinterest-hilo.s3.us-east-1.amazonaws.com pinterest-sim-toontown.s3.amazonaws.com pinterest-sim-toontown.s3.us-east-1.amazonaws.com pinterest-media-upload.s3.amazonaws.com pinterest-media-upload.s3.us-east-1.amazonaws.com pinterest-media-upload.s3-accelerate.amazonaws.com pinterest-media-upload.s3-accelerate.us-east-1.amazonaws.com pinterest-milwaukee.s3.amazonaws.com pinterest-milwaukee.s3.us-east-1.amazonaws.com pinterest-poughkeepsie.s3.amazonaws.com pinterest-poughkeepsie.s3.us-east-1.amazonaws.com pinterest-waterloo.s3.amazonaws.com pinterest-waterloo.s3.us-east-1.amazonaws.com pinterest-plymouth.s3.amazonaws.com pinterest-plymouth.s3.us-east-1.amazonaws.com pinterest-salvador.s3.us-east-1.amazonaws.com pinterest-yamagata.s3.amazonaws.com pinterest-yamagata.s3.us-east-1.amazonaws.com *.cedexis.com *.cedexis-radar.net *.tvpixel.com api.pinadmin.com *.live-video.net https://*.daily.co https://*.pluot.blue wss://*.wss.daily.co; form-action \'self\' *.adyen.com *.sofort.com *.tink.com *.adyenpayments.com; frame-src \'self\' *.pinimg.com *.pinterest.com *.adyen.com static-sandbox.dlocal.com static.dlocal.com *.google.com *.facebook.com www.recaptcha.net pinterest-hilo.s3.amazonaws.com pinterest-hilo.s3.us-east-1.amazonaws.com pinterest-sim-toontown.s3.amazonaws.com pinterest-sim-toontown.s3.us-east-1.amazonaws.com pinterest-milwaukee.s3.amazonaws.com pinterest-milwaukee.s3.us-east-1.amazonaws.com pinterest-waterloo.s3.amazonaws.com pinterest-waterloo.s3.us-east-1.amazonaws.com pinterest-tolu.s3.amazonaws.com *.pinterdev.com content.googleapis.com *.youtube.com *.youtube-nocookie.com *.ytimg.com player.vimeo.com calendly.com vine.co bid.g.doubleclick.net *.fls.doubleclick.net pinlogs.s3.amazonaws.com pinlogs.s3.us-east-1.amazonaws.com advertising-delivery-metric-reports.s3.amazonaws.com advertising-delivery-metric-reports.s3.us-east-1.amazonaws.com servedby.flashtalking.com pinterest-uk.admo.tv pinterest-uk-web.admo.tv fbrpc://call *.linkedin.com px.ads.linkedin.com; media-src \'self\' blob: data: *.pinimg.com *.live-video.net; object-src \'self\'; script-src \'nonce-f89465695d77502644c1eed4d9b4b460\' \'strict-dynamic\' \'self\' blob: \'unsafe-inline\' *.pinimg.com *.pinterest.com *.adyen.com js.dlocal.com js-sandbox.dlocal.com static-sandbox.dlocal.com static.dlocal.com *.adyenpayments.com \'report-sample\' *.google.com connect.facebook.net *.google-analytics.com *.facebook.com *.googleadservices.com *.doubleclick.net *.googletagmanager.com radar.cedexis.com *.cedexis-test.com www.gstatic.com/recaptcha/ www.gstatic.cn/recaptcha/ www.recaptcha.net \'wasm-unsafe-eval\'; worker-src \'self\' blob: \'unsafe-inline\'; report-uri /_/_/csp_report/?rid=1299431844478007; frame-ancestors \'self\' , script-src \'self\' blob: \'unsafe-inline\' *.pinimg.com *.pinterest.com *.adyen.com js.dlocal.com js-sandbox.dlocal.com static-sandbox.dlocal.com static.dlocal.com *.adyenpayments.com \'report-sample\' *.google.com connect.facebook.net *.google-analytics.com *.facebook.com *.googleadservices.com *.doubleclick.net *.googletagmanager.com radar.cedexis.com *.cedexis-test.com www.gstatic.com/recaptcha/ www.gstatic.cn/recaptcha/ www.recaptcha.net \'wasm-unsafe-eval\'; report-uri /_/_/csp_report/?rid=1299431844478007' + ], + 'content-security-policy-report-only' => [ + 'img-src \'self\' blob: data: *.pinimg.com *.pinterest.com *.google.com *.facebook.com *.cedexis.com *.cedexis-test.com *.citrix.com *.tvpixel.com; report-uri /_/_/csp_report/?reportonly' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'origin-trial' => [ + 'AvlUIFJouPpJAKljRGh7EnYm2Brnx/eu51h39Z7p11vbzNlw2YhkUhxvxZdkS709VlGGNw4Gcg/a9mAzHDrEcQ0AAAB5eyJvcmlnaW4iOiJodHRwczovL3BpbnRlcmVzdC5jb206NDQzIiwiZmVhdHVyZSI6IlNlbmRGdWxsVXNlckFnZW50QWZ0ZXJSZWR1Y3Rpb24iLCJleHBpcnkiOjE2ODQ4ODYzOTksImlzU3ViZG9tYWluIjp0cnVlfQ==' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Full,Sec-CH-UA-Full-Version-List,Sec-CH-UA-Model,Sec-CH-UA-Platform-Version' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'x-async-render' => [ + 'true' + ], + 'link' => [ + '; rel=preconnect; crossorigin=anonymous, ; rel=preconnect; crossorigin=anonymous, ; rel=preconnect; crossorigin=anonymous,; rel="alternate"; type="application/json+oembed" title="Find inspiration on Pinterest today!"' + ], + 'x-envoy-upstream-service-time' => [ + '162' + ], + 'content-encoding' => [ + 'br' + ], + 'referrer-policy' => [ + 'origin' + ], + 'x-pinterest-rid' => [ + '1299431844478007' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:18 GMT' + ], + 'vary' => [ + 'User-Agent, Accept-Encoding' + ], + 'x-cdn' => [ + 'fastly' + ], + 'alt-svc' => [ + 'h3=":443";ma=600' + ], + 'pinterest-generated-by' => [ + 'coreapp-webapp-prod-0a01122b' + ], + 'pinterest-version' => [ + 'f8146f7' + ], + 'Content-Location' => [ + 'https://www.pinterest.com/pin/106890191127977979/' + ], + 'X-Request-Time' => [ + '0.607 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '
' +]; diff --git a/tests/cache/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.7a0f9d85780cf81f4144f504601653cf.php b/tests/cache/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.7a0f9d85780cf81f4144f504601653cf.php new file mode 100644 index 00000000..041123be --- /dev/null +++ b/tests/cache/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.7a0f9d85780cf81f4144f504601653cf.php @@ -0,0 +1,97 @@ + [ + 'date' => [ + 'Sun, 04 Apr 2021 15:27:35 GMT' + ], + 'content-type' => [ + 'application/json+oembed;charset=UTF-8' + ], + 'content-length' => [ + '214' + ], + 'set-cookie' => [ + '__cfduid=d01727aca1a4b5f855dd1bd6f717ea1971617550054; expires=Tue, 04-May-21 15:27:34 GMT; path=/; domain=.www.politico.com; HttpOnly; SameSite=Lax; Secure' + ], + 'cf-ray' => [ + '63ab8fbf9dfcff10-MAD' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'age' => [ + '0' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate, stale-if-error=604800' + ], + 'expires' => [ + '0' + ], + 'strict-transport-security' => [ + 'max-age=31536000 ; includeSubDomains' + ], + 'via' => [ + '1.1 varnish (Varnish/6.3)' + ], + 'cf-cache-status' => [ + 'DYNAMIC' + ], + 'access-control-allow-credentials' => [ + 'true' + ], + 'cf-debug' => [ + 'no-cache header' + ], + 'cf-request-id' => [ + '093f182bbd0000ff109517e000000001' + ], + 'expect-ct' => [ + 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"' + ], + 'pragma' => [ + 'no-cache' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-varnish' => [ + '153183566' + ], + 'x-varnish-cache' => [ + 'MISS' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=RlW5z%2FXnPhJckw85XBfI5jqlFSnB9ZXEANMvhMcCgI57v1Ty%2Fo0LCRUcH0drmS40x5UuwxGlDtBVKcYRyz0DtND2UkyzbnB20tHzaskJTZho"}],"max_age":604800,"group":"cf-nel"}' + ], + 'nel' => [ + '{"report_to":"cf-nel","max_age":604800}' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare' + ], + 'Content-Location' => [ + 'https://www.politico.com/story/2013/12/presidents-barack-obama-george-w-bush-second-term-101314?_embed=true&_format=oembed' + ], + 'X-Request-Time' => [ + '0.811 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"rich","html":""}' +]; diff --git a/tests/cache/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.html.php b/tests/cache/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.html.php new file mode 100644 index 00000000..12ef2809 --- /dev/null +++ b/tests/cache/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.html.php @@ -0,0 +1,103 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:58:51 GMT', + 'Mon, 10 Jun 2024 15:58:51 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=UTF-8' + ], + 'content-length' => [ + '167' + ], + 'connection' => [ + 'keep-alive' + ], + 'cache-control' => [ + 'max-age=3600', + 'private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 16:58:51 GMT', + 'Thu, 01 Jan 1970 00:00:01 GMT' + ], + 'location' => [ + 'https://www.politico.com/story/2013/12/presidents-barack-obama-george-w-bush-second-term-101314.html' + ], + 'set-cookie' => [ + '__cf_bm=K3wPfc3VLdzRO5zcuVs08HK4YpxdpS9AB6CK.PV2TgE-1718035131-1.0.1.1-4HPPX6G.3nH0CNPCbR_jeegbaFYM44BxW.OfzoplKrjqpTe_OcHCE0MzIiSKrJg4jxCNedCsrggiKUf3mpR1Lg; path=/; expires=Mon, 10-Jun-24 16:28:51 GMT; domain=.www.politico.com; HttpOnly' + ], + 'report-to' => [ + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=elmCx1huhNHE9s7f6z0oshKqSVUfjHXPJyn2OPgnabfO6EffmLUllY%2F9Cah1GJz60sdvAyydgjnXn1SMxt9Ue2dXfDcbyHYfe0397QHPBdobOB1NpTvSF7tKn7UQM3U05JM%3D"}],"group":"cf-nel","max_age":604800}', + '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=et%2FFqKwrcXMZ6H9qw27C%2BdxKGdTtTbPvHReurEFjVbjxjcnftQEYr2EBacjjdySqbPtevV96M3ZgmnkQqGRUrgjJNLSnoiTj%2F%2F3m39RS5G6yRfeCGYrmvyk7%2BtHABPVBCkc%3D"}],"group":"cf-nel","max_age":604800}' + ], + 'nel' => [ + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', + '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}' + ], + 'vary' => [ + 'Accept-Encoding', + 'Accept-Encoding' + ], + 'server' => [ + 'cloudflare', + 'cloudflare' + ], + 'cf-ray' => [ + '891a90b5893b1ba7-MAD HTTP/2 403', + '891a90b63ed91bbb-MAD' + ], + 'accept-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'critical-ch' => [ + 'Sec-CH-UA-Bitness, Sec-CH-UA-Arch, Sec-CH-UA-Full-Version, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Platform, Sec-CH-UA, UA-Bitness, UA-Arch, UA-Full-Version, UA-Mobile, UA-Model, UA-Platform-Version, UA-Platform, UA' + ], + 'cross-origin-embedder-policy' => [ + 'require-corp' + ], + 'cross-origin-opener-policy' => [ + 'same-origin' + ], + 'cross-origin-resource-policy' => [ + 'same-origin' + ], + 'origin-agent-cluster' => [ + '?1' + ], + 'permissions-policy' => [ + 'accelerometer=(),autoplay=(),browsing-topics=(),camera=(),clipboard-read=(),clipboard-write=(),geolocation=(),gyroscope=(),hid=(),interest-cohort=(),magnetometer=(),microphone=(),payment=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),sync-xhr=(),usb=()' + ], + 'referrer-policy' => [ + 'same-origin' + ], + 'x-content-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'cf-mitigated' => [ + 'challenge' + ], + 'cf-chl-out' => [ + 'QsUECuaXU8fMJ/8RL4sf8fOxbZaE0uNs8Yt8L5qmi+G700rBcn+lyFe8w6jMHTKyU79q/cZGTL/HeLugGGDN72T35K1sktohDG4dlq/jgcgwr6cQzFvkbqbQ0n8bk0/dWAwVkti8WjuwK8lHWZQEGA==$esnkgaSmfIbV4IONA4GHtQ==' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://www.politico.com/story/2013/12/presidents-barack-obama-george-w-bush-second-term-101314.html' + ], + 'X-Request-Time' => [ + '0.169 ms' + ] + ], + 'statusCode' => 403, + 'reasonPhrase' => 'Forbidden', + 'body' => 'Just a moment...
' +]; diff --git a/tests/cache/www.reddit.com.oembed.3ede068a9562cbb20cda739887ac4147.php b/tests/cache/www.reddit.com.oembed.3ede068a9562cbb20cda739887ac4147.php new file mode 100644 index 00000000..5a1b998c --- /dev/null +++ b/tests/cache/www.reddit.com.oembed.3ede068a9562cbb20cda739887ac4147.php @@ -0,0 +1,62 @@ + [ + 'content-type' => [ + 'application/json; charset=UTF-8' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'content-encoding' => [ + 'gzip' + ], + 'cache-control' => [ + 'max-age=0, must-revalidate' + ], + 'x-moose' => [ + 'majestic' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:27:40 GMT' + ], + 'via' => [ + '1.1 varnish' + ], + 'vary' => [ + 'accept-encoding' + ], + 'set-cookie' => [ + 'csv=1; Max-Age=63072000; Domain=.reddit.com; Path=/; Secure; SameSite=None', + 'edgebucket=pIsVfIq9vXZdZFxGRS; Domain=reddit.com; Max-Age=63071999; Path=/; secure' + ], + 'strict-transport-security' => [ + 'max-age=15552000; includeSubDomains; preload' + ], + 'server' => [ + 'snooserv' + ], + 'content-length' => [ + '402' + ], + 'Content-Location' => [ + 'https://www.reddit.com/oembed?url=https%3A%2F%2Fwww.reddit.com%2Fr%2Finvesting%2Fcomments%2F7pfpeq%2Fbuffett_on_cyrptocurrencies_i_can_say_almost_with%2F&format=json' + ], + 'X-Request-Time' => [ + '0.184 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"provider_url": "https://www.reddit.com/", "version": "1.0", "title": "Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'", "provider_name": "reddit", "type": "rich", "html": "\\n \\u003Cblockquote class=\\"reddit-card\\" \\u003E\\n \\u003Ca href=\\"https://www.reddit.com/r/investing/comments/7pfpeq/buffett_on_cyrptocurrencies_i_can_say_almost_with/?ref_source=embed\\u0026amp;ref=share\\"\\u003EBuffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'\\u003C/a\\u003E from\\n \\u003Ca href=\\"https://www.reddit.com/r/investing///"\\u003Einvesting\\u003C/a\\u003E\\n \\u003C/blockquote\\u003E\\n \\u003Cscript async src=\\"https://embed.redditmedia.com/widgets/platform.js//" charset=\\"UTF-8\\"\\u003E\\u003C/script\\u003E\\n", "author_name": "dennisrieves"}' +]; diff --git a/tests/cache/www.reddit.com.oembed.89faebb97139ce53a083a645bddfc9ee.php b/tests/cache/www.reddit.com.oembed.89faebb97139ce53a083a645bddfc9ee.php new file mode 100644 index 00000000..137eba98 --- /dev/null +++ b/tests/cache/www.reddit.com.oembed.89faebb97139ce53a083a645bddfc9ee.php @@ -0,0 +1,61 @@ + [ + 'content-encoding' => [ + 'gzip' + ], + 'content-type' => [ + 'application/json' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:57:25 GMT' + ], + 'via' => [ + '1.1 varnish' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'cache-control' => [ + 'private, max-age=3600' + ], + 'server' => [ + 'snooserv' + ], + 'report-to' => [ + '{"group": "w3-reporting-nel", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-nel.reddit.com/reports" }]}, {"group": "w3-reporting", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting.reddit.com/reports" }]}, {"group": "w3-reporting-csp", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-csp.reddit.com/reports" }]}' + ], + 'nel' => [ + '{"report_to": "w3-reporting-nel", "max_age": 14400, "include_subdomains": false, "success_fraction": 1.0, "failure_fraction": 1.0}' + ], + 'content-length' => [ + '398' + ], + 'Content-Location' => [ + 'https://www.reddit.com/oembed?url=https%3A%2F%2Fwww.reddit.com%2Fr%2Finvesting%2Fcomments%2F7pfpeq%2Fbuffett_on_cyrptocurrencies_i_can_say_almost_with%2F%3Frdt%3D59640&format=json' + ], + 'X-Request-Time' => [ + '0.468 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"author_name":"dennisrieves","html":"\\u003cblockquote class=\\"reddit-embed-bq\\" style=\\"height:316px\\" \\u003e\\n\\u003ca href=\\"https://www.reddit.com/r/investing/comments/7pfpeq/buffett_on_cyrptocurrencies_i_can_say_almost_with///"\\u003eBuffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'\\u003c/a\\u003e\\u003cbr\\u003e by\\n\\u003ca href=\\"https://www.reddit.com/user/dennisrieves///"\\u003eu/dennisrieves\\u003c/a\\u003e in\\n\\u003ca href=\\"https://www.reddit.com/r/investing///"\\u003einvesting\\u003c/a\\u003e\\n\\u003c/blockquote\\u003e\\n\\u003cscript async src=\\"https://embed.reddit.com/widgets.js//" charset=\\"UTF-8\\"\\u003e\\u003c/script\\u003e","provider_name":"reddit","provider_url":"https://www.reddit.com/","title":"Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'","type":"rich","height":316}' +]; diff --git a/tests/cache/www.reddit.com.oembed.ce357a92629d244f4d53ac3643420128.php b/tests/cache/www.reddit.com.oembed.ce357a92629d244f4d53ac3643420128.php new file mode 100644 index 00000000..d5445d0b --- /dev/null +++ b/tests/cache/www.reddit.com.oembed.ce357a92629d244f4d53ac3643420128.php @@ -0,0 +1,61 @@ + [ + 'content-encoding' => [ + 'gzip' + ], + 'content-type' => [ + 'application/json' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:54 GMT' + ], + 'via' => [ + '1.1 varnish' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'cache-control' => [ + 'private, max-age=3600' + ], + 'server' => [ + 'snooserv' + ], + 'report-to' => [ + '{"group": "w3-reporting-nel", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-nel.reddit.com/reports" }]}, {"group": "w3-reporting", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting.reddit.com/reports" }]}, {"group": "w3-reporting-csp", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-csp.reddit.com/reports" }]}' + ], + 'nel' => [ + '{"report_to": "w3-reporting-nel", "max_age": 14400, "include_subdomains": false, "success_fraction": 1.0, "failure_fraction": 1.0}' + ], + 'content-length' => [ + '398' + ], + 'Content-Location' => [ + 'https://www.reddit.com/oembed?url=https%3A%2F%2Fwww.reddit.com%2Fr%2Finvesting%2Fcomments%2F7pfpeq%2Fbuffett_on_cyrptocurrencies_i_can_say_almost_with%2F%3Frdt%3D46144&format=json' + ], + 'X-Request-Time' => [ + '0.499 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"author_name":"dennisrieves","html":"\\u003cblockquote class=\\"reddit-embed-bq\\" style=\\"height:316px\\" \\u003e\\n\\u003ca href=\\"https://www.reddit.com/r/investing/comments/7pfpeq/buffett_on_cyrptocurrencies_i_can_say_almost_with///"\\u003eBuffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'\\u003c/a\\u003e\\u003cbr\\u003e by\\n\\u003ca href=\\"https://www.reddit.com/user/dennisrieves///"\\u003eu/dennisrieves\\u003c/a\\u003e in\\n\\u003ca href=\\"https://www.reddit.com/r/investing///"\\u003einvesting\\u003c/a\\u003e\\n\\u003c/blockquote\\u003e\\n\\u003cscript async src=\\"https://embed.reddit.com/widgets.js//" charset=\\"UTF-8\\"\\u003e\\u003c/script\\u003e","provider_name":"reddit","provider_url":"https://www.reddit.com/","title":"Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'","type":"rich","height":316}' +]; diff --git a/tests/cache/www.reddit.com.r-investing-comments-7pfpeq-buffett_on_cyrptocurrencies_i_can_say_almost_with.php b/tests/cache/www.reddit.com.r-investing-comments-7pfpeq-buffett_on_cyrptocurrencies_i_can_say_almost_with.php new file mode 100644 index 00000000..f246fa40 --- /dev/null +++ b/tests/cache/www.reddit.com.r-investing-comments-7pfpeq-buffett_on_cyrptocurrencies_i_can_say_almost_with.php @@ -0,0 +1,4401 @@ + [ + 'retry-after' => [ + '0' + ], + 'set-cookie' => [ + 'rdt=ff42132d7e5c8d2da7787653b428347d; path=/; domain=.reddit.com; samesite=none; secure;', + 'edgebucket=CWpVhbdKkbRMOlDuJJ; Domain=reddit.com; Max-Age=63071999; Path=/; secure', + 'loid=00000000127ecr1w69.2.1718035133692.Z0FBQUFBQm1aeUs5WWhCRjlyeWFxYXpyTXV3a3Vya0RKNVFveTBEWFVJVmliZmRvMmxyUHRmZkhmTVRsZHk0WVBLUWFETXA0b3NKVXI4WXFoc3R0a0ZISnRvcmNVMUswd3A0Ty1oeVBkcVk3TW9sc3dGOEZlV1ZuYmh6czdzbjNvWlU3ZGdGc1RYeXk; path=/; expires=Wed, 10 Jun 2026 15:58:53 GMT; domain=.reddit.com; samesite=none; secure', + 'session_tracker=imaejppmjdabpkklqb.0.1718035133695.Z0FBQUFBQm1aeUs5V1VFTTV5MFlrdW0xLVF6RUpWVzNGaGhGanFaVlQzZEJnX0diN3ZlNUZwUDBJel9GeU95Qk96aTNTRXJDVzhmRXRyNVhkajdoS0tJMzZZa1JDUUVhV1lZamswc1ZENkhGZ08tMXFXVDZiaWM3N3J2WTBTcmdWcHNqTGRFcUxmOXc; path=/; domain=.reddit.com; secure; SameSite=None; Secure', + 'csrf_token=b1846cedfdac34e1fd2a65aa49159a3b; path=/; domain=.reddit.com; samesite=strict; secure', + 'token_v2=eyJhbGciOiJSUzI1NiIsImtpZCI6IlNIQTI1NjpzS3dsMnlsV0VtMjVmcXhwTU40cWY4MXE2OWFFdWFyMnpLMUdhVGxjdWNZIiwidHlwIjoiSldUIn0.eyJzdWIiOiJsb2lkIiwiZXhwIjoxNzE4MTIxNTMzLjY5Mjk1NywiaWF0IjoxNzE4MDM1MTMzLjY5Mjk1NywianRpIjoic3ExWDRWTWNUQVJqMTFzZnQ3VG80b2FKRjdWdFpBIiwiY2lkIjoiMFItV0FNaHVvby1NeVEiLCJsaWQiOiJ0Ml8xMjdlY3IxdzY5IiwibGNhIjoxNzE4MDM1MTMzNjkyLCJzY3AiOiJlSnhra2RHT3REQUloZC1sMXo3Ql95cF9OaHRzY1lhc0xRYW9rM243RFZvY2s3MDdjTDRpSFA4bktJcUZMRTJ1QktHa0tXRUZXdE9VTmlMdjU4eTlPWkVGU3lGVFI4NDN5d29rYVVwUFVtTjVweWxSd1daa0xsZmFzVUtEQjZZcFZTNloyMEtQUzV2UTNJMUZ6MDZNcWx4V0h0VFlvM0pwYkdNSzJ4UGp6Y1pxUXlxdXk2bE1ZRmtvbjhXTGZ2eUctdFktZjdiZmhIWXdyS2dLRF9UT3VGeHdZX0hERkhiX25wcjBiRjJ3cUwzWGc5US0xLU4yN2JObW9kbTVfVnpQdnphU2NUbUc1aWZZdjd0LUNSMTQ1SG1aVVFjd1lnMF95ckFqNl9Ddk9vREtCUVdNSlloUEk1QXJsMl9fSmRpdVRmOGF0eWQtLUdiRVRXXzRyUm1vNXhMRW9VX2o2emNBQVBfX1hEX2U0dyIsImZsbyI6MX0.QlgGU3Bq3Ccl4O1bK6jSeSoEOn2JKm8V6uStznI3qaaCKFV2IDJaoi1CGaMQ-rOKRwgaTPqrLe32VnPnZkNPp9uqrXM6Y2lexH0IXDn5ozSaFKU7UxbD4-CZzrdmeOBMT2l96s9ve2aocqu7cN3Hn6Zpog1RX0Pr4_TLXVqBxdjPzAfYpRhRb4AUaHztGQYXVSn4dts5X7H2QPLSWxUg06Eh7uc_Tbw-MR95U-LgOdeDUNmVpa2dYiG5MwkBTtYtjvza2_9Auh9ZcIv1uzW0fpJkdDPieRHTaVw-B3DP8_EPl43t9jOPRMjQU85PKlGe-uWvstF49Nyg7gIFb3FE9g; Path=/; Domain=reddit.com; Expires=Tue, 11 Jun 2024 15:58:53 GMT; HttpOnly; Secure', + 'theme=; path=/r/; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=.reddit.com; secure', + 'csv=2; Max-Age=63072000; Domain=.reddit.com; Path=/; Secure; SameSite=None' + ], + 'location' => [ + '/r/investing/comments/7pfpeq/buffett_on_cyrptocurrencies_i_can_say_almost_with/?rdt=46144' + ], + 'content-type' => [ + 'text/html; charset=utf-8', + 'text/html; charset=utf-8' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:53 GMT', + 'Mon, 10 Jun 2024 15:58:53 GMT' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains', + 'max-age=31536000; includeSubdomains' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block', + '1; mode=block' + ], + 'cache-control' => [ + 'private, max-age=3600', + 'private, s-maxage=1, max-age=1, must-revalidate' + ], + 'server' => [ + 'snooserv', + 'snooserv' + ], + 'report-to' => [ + '{"group": "w3-reporting-nel", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-nel.reddit.com/reports" }]}, {"group": "w3-reporting", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting.reddit.com/reports" }]}, {"group": "w3-reporting-csp", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-csp.reddit.com/reports" }]}', + '{"group": "w3-reporting-nel", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-nel.reddit.com/reports" }]}, {"group": "w3-reporting", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting.reddit.com/reports" }]}, {"group": "w3-reporting-csp", "max_age": 14400, "include_subdomains": true, "endpoints": [{ "url": "https://w3-reporting-csp.reddit.com/reports" }]}' + ], + 'nel' => [ + '{"report_to": "w3-reporting-nel", "max_age": 14400, "include_subdomains": false, "success_fraction": 1.0, "failure_fraction": 1.0}', + '{"report_to": "w3-reporting-nel", "max_age": 14400, "include_subdomains": false, "success_fraction": 1.0, "failure_fraction": 1.0}' + ], + 'content-length' => [ + '407 HTTP/2 200' + ], + 'content-encoding' => [ + 'gzip' + ], + 'content-security-policy' => [ + 'child-src \'self\' blob: accounts.google.com;connect-src \'self\' events.redditmedia.com o418887.ingest.sentry.io *.redd.it *.reddit.com www.redditstatic.com vimeo.com alb.reddit.com accounts.google.com/gsi/ w3-reporting.reddit.com reddit-uploaded-media.s3-accelerate.amazonaws.com reddit-uploaded-video.s3-accelerate.amazonaws.com reddit-subreddit-uploaded-media.s3-accelerate.amazonaws.com wss://*.wss.redditmedia.com wss://gql-realtime.reddit.com *.giphy.com js.stripe.com support.reddithelp.com matrix.redditspace.com;default-src \'self\';font-src \'self\' data:;form-action \'none\';frame-ancestors \'self\' *.reddit.com *.snooguts.net;frame-src \'self\' www.reddit.com www.youtube-nocookie.com player.vimeo.com *.redditmedia.com cdn.embedly.com redgifs.com www.redgifs.com accounts.google.com/gsi/ www.google.com/recaptcha/ recaptcha.google.com/recaptcha/ js.stripe.com hooks.stripe.com;img-src \'self\' data: blob: https:;manifest-src \'self\' www.redditstatic.com;media-src \'self\' blob: data: *.redd.it www.redditstatic.com matrix.redditspace.com;object-src \'none\';script-src \'self\' \'unsafe-inline\' \'unsafe-eval\' www.redditstatic.com www.google.com/recaptcha/ js.stripe.com accounts.google.com/gsi/client \'nonce-YtlZrjMDCft7pLXdwIaJkg==\';style-src \'self\' \'unsafe-inline\' www.redditstatic.com *.reddit.com accounts.google.com/gsi/style;style-src-attr \'unsafe-inline\';worker-src \'self\' blob:;report-to csp;report-uri https://w3-reporting-csp.reddit.com/reports' + ], + 'content-security-policy-report-only' => [ + 'object-src \'none\';script-src \'nonce-YtlZrjMDCft7pLXdwIaJkg==\' \'unsafe-inline\' \'unsafe-eval\' \'strict-dynamic\' https:;frame-ancestors \'self\' *.reddit.com *.snooguts.net;base-uri \'self\';report-to csp;report-uri https://w3-reporting-csp.reddit.com/reports' + ], + 'x-is-wrs' => [ + 'false' + ], + 'x-ratelimit-remaining' => [ + '198' + ], + 'x-ratelimit-used' => [ + '2' + ], + 'vary' => [ + 'Accept-Encoding,accept-language' + ], + 'Content-Location' => [ + 'https://www.reddit.com/r/investing/comments/7pfpeq/buffett_on_cyrptocurrencies_i_can_say_almost_with/?rdt=46144' + ], + 'X-Request-Time' => [ + '0.368 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => ' + + + + Reddit - Dive into anything + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Skip to main content + + + + + + + + + + + + + + +
+

+ Reddit and its partners use cookies and similar technologies to provide you with a better experience. +

+

+ By accepting all cookies, you agree to our use of cookies to deliver and maintain our services and site, improve the quality of Reddit, personalize Reddit content and advertising, and measure the effectiveness of advertising. +

+

+ By rejecting non-essential cookies, Reddit may still use certain cookies to ensure the proper functionality of our platform. +

+

+ For more information, please see our + Cookie Notice + and our + Privacy Policy. +

+
+
+
+ + + + + +
+
+ +
+

+ Get the Reddit app +

+
+ +
+
+
+
+ Scan this QR code to download the app now +
+ +
+ Or check it out in the app stores +
+ +
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + +
+ +
+ + Go to investing + +
+
+
+ +
+ + + + + + + r/investing +
+
+
+ +
+
+ + + + + + r/investing + + + + + + +
+

+ +

+
+
+ + + + + Members + + + + + + + + Online + + +
+
+
+
+
+ +
+
+ + + + +
+
+ + +
+ + + dennisrieves +
+ +
+ +
+
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
+

+ Buffett on cyrptocurrencies: 'I can say almost with certainty that they will come to a bad ending' +

+ + + + + + + +
+ News +
+
+ +
+
+ +
+ + + +
+
+
+

+ Bitcoin and other cryptocurrencies "will come to a bad ending," billionaire investor Warren Buffett told CNBC on Wednesday. https://www.cnbc.com/2018/01/10/buffett-says-cyrptocurrencies-will-almost-certainly-end-badly.html +

+
+
+
+ + + +
+ +
+ Archived post. New comments cannot be posted and votes cannot be cast. +
+
+ + + + + + + + +
+
+ +
+ + + +
+ +
+ + + + + + + + + +
+ + + + + + + + +
+ + + + + + + +
+ + + + + + + + + + ' +]; diff --git a/tests/cache/www.scribd.com.doc-110799637-synthesis-of-knowledge-effects-of-fire-and-thinning-treatments-on-understory-vegetation-in-dry-u-s-forests.php b/tests/cache/www.scribd.com.doc-110799637-synthesis-of-knowledge-effects-of-fire-and-thinning-treatments-on-understory-vegetation-in-dry-u-s-forests.php new file mode 100644 index 00000000..e40b029a --- /dev/null +++ b/tests/cache/www.scribd.com.doc-110799637-synthesis-of-knowledge-effects-of-fire-and-thinning-treatments-on-understory-vegetation-in-dry-u-s-forests.php @@ -0,0 +1,4186 @@ + [ + 'connection' => [ + 'close' + ], + 'content-length' => [ + '0', + '476136' + ], + 'server' => [ + 'Varnish', + 'envoy', + 'envoy' + ], + 'retry-after' => [ + '0' + ], + 'location' => [ + 'https://www.scribd.com/doc/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests', + 'https://www.scribd.com/document/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:54 GMT', + 'Mon, 10 Jun 2024 15:58:54 GMT', + 'Mon, 10 Jun 2024 15:58:55 GMT' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish', + '1.1 varnish' + ], + 'x-served-by' => [ + 'cache-mad2200105-MAD', + 'cache-mad22043-MAD', + 'cache-mad22043-MAD' + ], + 'x-cache' => [ + 'HIT', + 'MISS', + 'MISS' + ], + 'x-cache-hits' => [ + '0', + '0', + '0' + ], + 'vary' => [ + 'HTTP/2 301', + 'X-Language-Locale,Accept-Encoding', + 'X-Language-Locale,X-Bot,X-Fastly-Mobile,Accept-Encoding' + ], + 'content-type' => [ + 'text/html; charset=utf-8', + 'text/html; charset=utf-8' + ], + 'cache-control' => [ + 'private, no-store', + 'public, no-cache' + ], + 'content-encoding' => [ + 'br', + 'br' + ], + 'content-security-policy' => [ + 'frame-ancestors \'self\'', + 'frame-ancestors \'self\'' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin', + 'strict-origin-when-cross-origin' + ], + 'set-cookie' => [ + 'scribd_ubtc=u%3D3c893475-bb0f-4b5e-9793-a416a3f70679%26h%3DvNri91D8blhL1GHCreM8YXpHq%2FA6Swp42IjtYRDAilQ%3D; domain=.scribd.com; path=/; expires=Fri, 10 Jun 2039 15:58:54 GMT; secure' + ], + 'status' => [ + '301 Moved Permanently', + '200 OK' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'x-download-options' => [ + 'noopen', + 'noopen' + ], + 'x-envoy-upstream-service-time' => [ + '77', + '282' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'x-permitted-cross-domain-policies' => [ + 'none', + 'none' + ], + 'x-request-id' => [ + 'db6d4c7b1aef773f5c6f9bcc7d1eeb9d9713767786c9aaba8f06358fac814973', + '73bf1c8eece0573179e1b244e2c7188444b923b6ca301650288714744062570e' + ], + 'x-runtime' => [ + '0.075303', + '0.280312' + ], + 'x-xss-protection' => [ + '1; mode=block', + '1; mode=block' + ], + 'x-timer' => [ + 'S1718035135.592549,VS0,VE177', + 'S1718035135.786349,VS0,VE548' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains', + 'max-age=63072000; includeSubDomains' + ], + 'alt-svc' => [ + 'h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400 HTTP/2 200', + 'h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400' + ], + 'etag' => [ + 'W/"2d313c730e73d68464bc0c1c644b97c2"' + ], + 'last-modified' => [ + 'Sat, 17 Mar 2018 18:55:48 GMT' + ], + 'link' => [ + '; rel=preload; as=script; critical, ; rel=preload; as=script; critical' + ], + 'age' => [ + '0' + ], + 'Content-Location' => [ + 'https://www.scribd.com/document/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests' + ], + 'X-Request-Time' => [ + '1.002 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Synthesis of Knowledge: Effects of Fire and Thinning Treatments On Understory Vegetation in Dry U.S. Forests | Download Free PDF | Disturbance (Ecology) | Wildfire
You are on page 1of 133
+ + + +
+ + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + +
+ +
+
+
+
+
+
+
+
+
+ + + + + +
+

Reward Your Curiosity

Everything you want to read.
Anytime. Anywhere. Any device.
No Commitment. Cancel anytime.
+
576648e32a3d8b82ca71961b7a986505
' +]; diff --git a/tests/cache/www.scribd.com.services-oembed.46d5191000d009f0a4c7e94ea84886e9.php b/tests/cache/www.scribd.com.services-oembed.46d5191000d009f0a4c7e94ea84886e9.php new file mode 100644 index 00000000..7fbe39b0 --- /dev/null +++ b/tests/cache/www.scribd.com.services-oembed.46d5191000d009f0a4c7e94ea84886e9.php @@ -0,0 +1,114 @@ + [ + 'connection' => [ + 'close' + ], + 'content-length' => [ + '0' + ], + 'server' => [ + 'Varnish', + 'envoy' + ], + 'retry-after' => [ + '0' + ], + 'location' => [ + 'https://www.scribd.com/services/oembed/?url=http%3A%2F%2Fwww.scribd.com%2Fdoc%2F110799637%2FSynthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests&format=json' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:56 GMT', + 'Mon, 10 Jun 2024 15:58:56 GMT' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish' + ], + 'x-served-by' => [ + 'cache-mad2200119-MAD', + 'cache-mad2200092-MAD' + ], + 'x-cache' => [ + 'HIT', + 'MISS' + ], + 'x-cache-hits' => [ + '0', + '0' + ], + 'vary' => [ + 'HTTP/2 200', + 'X-Language-Locale,Accept-Encoding' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'cache-control' => [ + 'private, no-store' + ], + 'content-encoding' => [ + 'br' + ], + 'content-security-policy' => [ + 'frame-ancestors \'self\'' + ], + 'etag' => [ + 'W/"a8fc2c006231501d07800a423842601b"' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'status' => [ + '200 OK' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-envoy-upstream-service-time' => [ + '27' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'x-request-id' => [ + '1959c392d2e78b23e08423f879b12053264063026d03967cab2baa188b263d04' + ], + 'x-runtime' => [ + '0.025856' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-timer' => [ + 'S1718035137.559602,VS0,VE128' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains' + ], + 'alt-svc' => [ + 'h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400' + ], + 'Content-Location' => [ + 'https://www.scribd.com/services/oembed/?url=http%3A%2F%2Fwww.scribd.com%2Fdoc%2F110799637%2FSynthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests&format=json' + ], + 'X-Request-Time' => [ + '0.219 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"rich","version":"1.0","provider_name":"Scribd","provider_url":"https://www.scribd.com/","cache_age":604800,"title":"Synthesis of Knowledge: Effects of Fire and Thinning Treatments on Understory Vegetation in Dry U.S. Forests","author_name":"Joint Fire Science Program","author_url":"https://www.scribd.com/user/151878975/Joint-Fire-Science-Program","thumbnail_url":"https://imgv2-2-f.scribdassets.com/img/document/110799637/111x142/9fc8621525/1718028294?v=1","thumbnail_width":164,"thumbnail_height":212,"html":"\\u003ciframe class=\\"scribd_iframe_embed\\" src=\\"https://www.scribd.com/embeds/110799637/content//" data-aspect-ratio=\\"1.2941176470588236\\" scrolling=\\"no\\" id=\\"110799637\\" width=\\"100%\\" height=\\"500\\" frameborder=\\"0\\"\\u003e\\u003c/iframe\\u003e\\u003cscript type=\\"text/javascript\\"\\u003e\\n (function() { var scribd = document.createElement(\\"script\\"); scribd.type = \\"text/javascript\\"; scribd.async = true; scribd.src = \\"https://www.scribd.com/javascripts/embed_code/inject.js//"; var s = document.getElementsByTagName(\\"script\\")[0]; s.parentNode.insertBefore(scribd, s); })()\\n \\u003c/script\\u003e"}' +]; diff --git a/tests/cache/www.scribd.com.services-oembed.c69c8e06ee9109540c058fe5f4173f18.php b/tests/cache/www.scribd.com.services-oembed.c69c8e06ee9109540c058fe5f4173f18.php new file mode 100644 index 00000000..a2213c3c --- /dev/null +++ b/tests/cache/www.scribd.com.services-oembed.c69c8e06ee9109540c058fe5f4173f18.php @@ -0,0 +1,105 @@ + [ + 'server' => [ + 'Varnish', + 'nginx' + ], + 'retry-after' => [ + '0' + ], + 'location' => [ + 'https://www.scribd.com/services/oembed/?url=https%3A%2F%2Fwww.scribd.com%2Fdocument%2F110799637%2FSynthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests&format=json' + ], + 'content-length' => [ + '0' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:27:41 GMT', + 'Sun, 04 Apr 2021 15:27:41 GMT' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish' + ], + 'connection' => [ + 'close' + ], + 'x-served-by' => [ + 'cache-mad22074-MAD', + 'cache-mad22070-MAD' + ], + 'x-cache' => [ + 'HIT', + 'MISS' + ], + 'x-cache-hits' => [ + '0', + '0' + ], + 'x-timer' => [ + 'S1617550061.425141,VS0,VE0' + ], + 'set-cookie' => [ + 'nway=9b4b3d62-7d1f-4c02-a8c9-1fdc44cd2a8d; max-age=86400; path=/; secure; httponly', + 'scribd_ubtc=u%3Db406a08f-1a76-42d8-b3c9-452a0945a983%26h%3DvPUxOApOOg1XJZc7%2BgKWhpVNKFeEitiohVoEVuSQA%2B8%3D; Domain=.scribd.com; Path=/; Expires=Tue, 11 Mar 2121 15:27:41 GMT; Secure HTTP/2 200', + 'scribd_ubtc=u%3D875155d3-ce43-4fce-b053-61000c029946%26h%3DJCUzf2g%2B8WLGLcsX7Uxln16T1DmBLh5cyoBHT%2BPYxPA%3D; domain=.scribd.com; path=/; expires=Fri, 04 Apr 2036 15:27:41 GMT; secure', + '_scribd_session=eyJzZXNzaW9uX2lkIjoiYzM5ZTlkNTQwZWMyODYxZDBkOTdiNzI3NzRjYmFkNTAifQ%3D%3D--7ace03e75a7eee27d2f73dab884b4a4f7be0befc; domain=.scribd.com; path=/; expires=Thu, 04 Apr 2024 15:27:41 GMT; secure; HttpOnly', + 'nway=7b1bfd1a-4dac-4a74-9e4b-b9dbc1794f17; max-age=86400; path=/; secure; httponly' + ], + 'cache-control' => [ + 'no-store', + 'no-store' + ], + 'vary' => [ + '', + 'Accept-Encoding, X-Language-Locale' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'status' => [ + '200 OK' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'content-security-policy' => [ + 'frame-ancestors \'self\'' + ], + 'x-request-id' => [ + '9b2efdd38def9d3618c3fd98c93fe5d5ef097a15610b78c29205ad50a514a6a2' + ], + 'x-runtime' => [ + '0.034203' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains; preload' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://www.scribd.com/services/oembed/?url=https%3A%2F%2Fwww.scribd.com%2Fdocument%2F110799637%2FSynthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests&format=json' + ], + 'X-Request-Time' => [ + '0.244 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"rich","version":"1.0","provider_name":"Scribd","provider_url":"https://www.scribd.com/","cache_age":604800,"title":"Synthesis of Knowledge: Effects of Fire and Thinning Treatments on Understory Vegetation in Dry U.S. Forests","author_name":"Joint Fire Science Program","author_url":"https://www.scribd.com/user/151878975/Joint-Fire-Science-Program","thumbnail_url":"https://imgv2-2-f.scribdassets.com/img/document/110799637/111x142/9fc8621525/1617346919?v=1","thumbnail_width":164,"thumbnail_height":212,"html":"\\u003ciframe class=\\"scribd_iframe_embed\\" src=\\"https://www.scribd.com/embeds/110799637/content//" data-aspect-ratio=\\"1.2941176470588236\\" scrolling=\\"no\\" id=\\"110799637\\" width=\\"100%\\" height=\\"500\\" frameborder=\\"0\\"\\u003e\\u003c/iframe\\u003e\\u003cscript type=\\"text/javascript\\"\\u003e\\n (function() { var scribd = document.createElement(\\"script\\"); scribd.type = \\"text/javascript\\"; scribd.async = true; scribd.src = \\"https://www.scribd.com/javascripts/embed_code/inject.js//"; var s = document.getElementsByTagName(\\"script\\")[0]; s.parentNode.insertBefore(scribd, s); })()\\n \\u003c/script\\u003e"}' +]; diff --git a/tests/cache/www.soundhelix.com.examples-mp3-soundhelix-song-1.mp3.php b/tests/cache/www.soundhelix.com.examples-mp3-soundhelix-song-1.mp3.php new file mode 100644 index 00000000..7cc294d4 --- /dev/null +++ b/tests/cache/www.soundhelix.com.examples-mp3-soundhelix-song-1.mp3.php @@ -0,0 +1,49 @@ + [ + 'x-content-type-options' => [ + 'nosniff' + ], + 'vary' => [ + 'User-Agent' + ], + 'last-modified' => [ + 'Sat, 05 Mar 2011 18:33:59 GMT' + ], + 'etag' => [ + '"887e4d-49dc0818373c0"' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'content-length' => [ + '8945229' + ], + 'cache-control' => [ + 'max-age=1209600' + ], + 'expires' => [ + 'Mon, 24 Jun 2024 15:59:05 GMT' + ], + 'content-type' => [ + 'audio/mpeg' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:05 GMT' + ], + 'server' => [ + 'Apache/2.4.59 (Unix)' + ], + 'Content-Location' => [ + 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3' + ], + 'X-Request-Time' => [ + '0.206 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '' +]; diff --git a/tests/cache/www.spreaker.com.user-angelclark-angel-clark-ice-cream-tocos.php b/tests/cache/www.spreaker.com.user-angelclark-angel-clark-ice-cream-tocos.php new file mode 100644 index 00000000..695da9b4 --- /dev/null +++ b/tests/cache/www.spreaker.com.user-angelclark-angel-clark-ice-cream-tocos.php @@ -0,0 +1,430 @@ + [ + 'server' => [ + 'CloudFront', + 'nginx' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:57 GMT', + 'Mon, 10 Jun 2024 15:58:57 GMT' + ], + 'content-type' => [ + 'text/html', + 'text/html; charset=utf-8' + ], + 'content-length' => [ + '167' + ], + 'connection' => [ + 'keep-alive' + ], + 'location' => [ + 'https://www.spreaker.com/user/angelclark/angel-clark-ice-cream-tocos' + ], + 'x-cache' => [ + 'Redirect from cloudfront', + 'Error from cloudfront' + ], + 'via' => [ + '1.1 7ae18d43f184af54ef9e0522b07572d8.cloudfront.net (CloudFront)', + '1.1 ab191356c2d8bb1592ce3dc82f816ccc.cloudfront.net (CloudFront)' + ], + 'x-amz-cf-pop' => [ + 'MAD56-P4', + 'MAD56-P4' + ], + 'alt-svc' => [ + 'h3=":443"; ma=86400', + 'h3=":443"; ma=86400' + ], + 'x-amz-cf-id' => [ + 'W90O5uQ3jyS7bGV6otYlCse_NWdis2XN9PX-rjiTpOXGKR2YimK5YQ== HTTP/2 404', + 'ZTjjl4nTc0UEBjOTk1BJkvoA7a28DQFiV3IIViqYYk_H30zW68C7Ng==' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'set-cookie' => [ + 'spreaker=74f03e4652fd8a931973480bf231100a; path=/; domain=.spreaker.com; secure; HttpOnly' + ], + 'expires' => [ + 'Thu, 19 Nov 1981 08:52:00 GMT' + ], + 'pragma' => [ + 'no-cache' + ], + 'cache-control' => [ + 'max-age=0, private, no-cache, no-store, must-revalidate, no-transform' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://www.spreaker.com/user/angelclark/angel-clark-ice-cream-tocos' + ], + 'X-Request-Time' => [ + '0.320 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => ' + + + + + + + + +Page not found + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+
+
+ + + +
+ +
+ + +
+
+
+ + +
+ + +
+ +
+ +
+
+ +
+ + +
+
+
+
+

OOPS!

+

We’re really sorry, but the page you’re looking for can’t be found

+ + +

+ You might have mis-typed the URL.
+ Please check it again.
+

+ +
+ +
+
+
+
+
+ +
+
+ + + +
+ + + +
+ + + + + + + + + + + + + + + + + +' +]; diff --git a/tests/cache/www.ted.com.services-v1-oembed.json.c1275f45b6ad69b10fe02d9566501128.php b/tests/cache/www.ted.com.services-v1-oembed.json.c1275f45b6ad69b10fe02d9566501128.php new file mode 100644 index 00000000..f24e7786 --- /dev/null +++ b/tests/cache/www.ted.com.services-v1-oembed.json.c1275f45b6ad69b10fe02d9566501128.php @@ -0,0 +1,79 @@ + [ + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'cache-control' => [ + 'no-transform, public, max-age=0, s-maxage=3600' + ], + 'etag' => [ + 'W/"7f154e9e9ebb93160bfdce66f33de894"' + ], + 'strict-transport-security' => [ + 'max-age=63072000; includeSubDomains' + ], + 'content-encoding' => [ + 'gzip' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'age' => [ + '0' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:58 GMT' + ], + 'via' => [ + '1.1 varnish' + ], + 'x-served-by' => [ + 'e02, cache-iad-kcgs7200074-IAD, cache-mad22033-MAD' + ], + 'x-cache' => [ + 'MISS, MISS' + ], + 'x-cache-hits' => [ + '0, 0' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'content-length' => [ + '690' + ], + 'Content-Location' => [ + 'https://www.ted.com/services/v1/oembed.json?url=https%3A%2F%2Fwww.ted.com%2Ftalks%2Fgeorge_monbiot_for_more_wonder_rewild_the_world' + ], + 'X-Request-Time' => [ + '0.217 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"type":"video","version":"1.0","width":560,"height":316,"title":"George Monbiot: For more wonder, rewild the world","description":"Wolves were once native to the US\' Yellowstone National Park -- until hunting wiped them out. But when, in 1995, the wolves began to come back (thanks to an aggressive management program), something interesting happened: the rest of the park began to find a new, more healthful balance. In a bold thought experiment, George Monbiot imagines a wilder world in which humans work to restore the complex, lost natural food chains that once surrounded us.","url":"https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world","author_name":"George Monbiot","provider_name":"TED","provider_url":"https://www.ted.com/","cache_age":300,"thumbnail_url":"https://pi.tedcdn.com/r/pe.tedcdn.com/images/ted/b4a648817c1a2102dc53dc2147bb1af2785067f0_1600x1200.jpg?h=316\\u0026w=560","thumbnail_width":560,"thumbnail_height":316,"author_url":"https://www.ted.com/speakers/george_monbiot","html":"\\u003ciframe src=\\"https://embed.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world//" width=\\"560\\" height=\\"316\\" frameborder=\\"0\\" scrolling=\\"no\\" webkitAllowFullScreen mozallowfullscreen allowFullScreen\\u003e\\u003c/iframe\\u003e"}' +]; diff --git a/tests/cache/www.ted.com.talks-george_monbiot_for_more_wonder_rewild_the_world.07a0d4dfc7fba14d52025577270bbe9c.php b/tests/cache/www.ted.com.talks-george_monbiot_for_more_wonder_rewild_the_world.07a0d4dfc7fba14d52025577270bbe9c.php new file mode 100644 index 00000000..f5daeb93 --- /dev/null +++ b/tests/cache/www.ted.com.talks-george_monbiot_for_more_wonder_rewild_the_world.07a0d4dfc7fba14d52025577270bbe9c.php @@ -0,0 +1,126 @@ + [ + 'connection' => [ + 'close' + ], + 'content-length' => [ + '0', + '62140' + ], + 'server' => [ + 'Varnish' + ], + 'retry-after' => [ + '0' + ], + 'location' => [ + 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=en' + ], + 'accept-ranges' => [ + 'bytes', + 'bytes' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:57 GMT', + 'Mon, 10 Jun 2024 15:58:58 GMT' + ], + 'via' => [ + '1.1 varnish', + '1.1 varnish' + ], + 'x-served-by' => [ + 'cache-mad22037-MAD', + 'td_b05fc2effc1a, cache-iad-kcgs7200050-IAD, cache-mad2200121-MAD' + ], + 'x-cache' => [ + 'HIT', + 'MISS, MISS' + ], + 'x-cache-hits' => [ + '0', + '0, 0' + ], + 'x-timer' => [ + 'S1718035138.752757,VS0,VE0 HTTP/2 200' + ], + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'x-powered-by' => [ + 'Zenith' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-permitted-cross-domain-policies' => [ + 'none' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubDomains' + ], + 'cache-control' => [ + 'no-transform, public, max-age=180' + ], + 'etag' => [ + 'W/"r4g8o40c484xf1"' + ], + 'content-encoding' => [ + 'gzip' + ], + 'age' => [ + '0' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'set-cookie' => [ + '_nu=1718035138; Expires=Sat, 09 Jun 2029 15:58:58 GMT; path=/', + '_abby=iIeQjGwVbvhDAp2; Expires=Sat, 09 Jun 2029 15:58:58 GMT; Path=/; Domain=.ted.com', + '_abby_post15s=b; Expires=Mon, 24 Jun 2024 15:58:58 GMT; Path=/', + '_abby_hero_form=b; Expires=Mon, 24 Jun 2024 15:58:58 GMT; Path=/' + ], + 'Content-Location' => [ + 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=en' + ], + 'X-Request-Time' => [ + '0.786 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'George Monbiot: For more wonder, rewild the world | TED Talk

For more wonder, rewild the world

1,270,832 views |
George Monbiot |
TEDGlobal 2013
• July 2013
' +]; diff --git a/tests/cache/www.tiktok.com.a3noticias-video-6806030056956251397.php b/tests/cache/www.tiktok.com.a3noticias-video-6806030056956251397.php new file mode 100644 index 00000000..9cedc28c --- /dev/null +++ b/tests/cache/www.tiktok.com.a3noticias-video-6806030056956251397.php @@ -0,0 +1,120 @@ + [ + 'content-type' => [ + 'text/html; charset=utf-8' + ], + 'content-security-policy' => [ + 'script-src \'unsafe-eval\' sf16-website-login.neutral.ttwstatic.com s20.tiktokcdn.com *.tiktokcdn-us.com www.google.com recaptcha.google.com js.hcaptcha.com client-api.arkoselabs.com www.gstatic.com connect.facebook.net; frame-src *.tiktok.com accounts.google.com www.google.com recaptcha.google.com www.facebook.com *.kakao.com lf16-web.tiktokcdn.com assets.braintreegateway.com appleid.apple.com access.line.me api.twitter.com h.online-metrix.net bytedance: newassets.hcaptcha.com client-api.arkoselabs.com; worker-src https: blob:; frame-ancestors tea-va.bytedance.net www.tiktok.com; default-src \'self\' \'unsafe-eval\' \'unsafe-inline\' blob: bytedance: data: wss://*.tiktok.com wss://*.tiktokv.com wss://*.tiktokv.eu wss://tiktok.com wss://tiktokv.com *.adsco.re *.adsintegrity.net *.akamaized.net *.amazonaws.com *.bing.com *.bitssec.com *.bytedapm.com *.bytedgame.com *.bytehwm-row.com *.byteicdn.com *.byteintl.com *.byteintl.net *.byteintlapi.com *.byteintlstatic.com *.bytelemon.com *.byteoversea.com *.byteoversea.net *.bytevcloudapi.com *.capcut.com *.cloudflare.com *.ctfassets.net *.doubleclick.net *.evbuc.com *.eventim.de *.facebook.com *.facebook.net *.fbsbx.com *.fcdnstatic-intl.com *.fdmstatic.com *.g-p-static.com *.gauthmath.com *.goofy-cdn.com *.goofy.app *.google-analytics.com *.google.ae *.google.at *.google.be *.google.bg *.google.bj *.google.by *.google.ca *.google.ch *.google.co.cr *.google.co.id *.google.co.il *.google.co.jp *.google.co.kr *.google.co.ma *.google.co.nz *.google.co.uk *.google.co.za *.google.com *.google.com.ar *.google.com.au *.google.com.bd *.google.com.br *.google.com.cy *.google.com.do *.google.com.ec *.google.com.gh *.google.com.lb *.google.com.mt *.google.com.my *.google.com.ng *.google.com.pe *.google.com.pk *.google.com.sa *.google.com.sg *.google.com.tr *.google.cz *.google.de *.google.dk *.google.dz *.google.ee *.google.es *.google.fi *.google.fr *.google.gr *.google.hr *.google.hu *.google.ie *.google.iq *.google.is *.google.it *.google.lt *.google.lu *.google.lv *.google.md *.google.nl *.google.no *.google.pl *.google.ps *.google.pt *.google.ro *.google.rs *.google.se *.google.si *.google.sk *.google.td *.google.tn *.googleapis.com *.googletagmanager.com *.gstatic.com *.hsforms.com *.hsforms.net *.ibytedtos.com *.ibyteimg.com *.isnssdk.com *.jumio.ai *.kakao.com *.lemon8-app.com *.lemon8cdn.com *.licdn.com *.linkedin.com *.midtrans.com *.muscdn.com *.musical.ly *.oecstatic.com *.omise.co *.pangle-ads.com *.paypal.com *.pipopay.com *.redditstatic.com *.resso.me *.sgsnssdk.com *.soundon.global *.tableau.com *.tiktok-row.net *.tiktok.com *.tiktok.ru *.tiktok.vn *.tiktokapis.com *.tiktokcdn-eu.com *.tiktokcdn-in.com *.tiktokcdn-us.com *.tiktokcdn.com *.tiktokcreativeone.com *.tiktokforbusinessoutbound.com *.tiktokglobalshop.com *.tiktokmusic.me *.tiktokshop.com *.tiktokstaticb.com *.tiktokus.info *.tiktokv.com *.tiktokv.eu *.tiktokv.us *.tiktokw.eu *.tiktokw.us *.topbuzzcdn.com *.ttlivecdn.com *.ttlstatic.com *.ttwstatic.com *.vimeo.com *.vodupload.com *.yahoo.co.jp *.yhgfb-static.com *.youtube-nocookie.com *.zhiliaoapp.com code.jquery.com facebook.com google.com i.ticketweb.com images.universe.com media.ticketmaster.eu res.cloudinary.com s1.ticketm.net static-label.frontgatetickets.com t.co tikitoks.com tiktok.com tiktok.ua tiktok.vn tiktokfollowersfree.com tiktokv.com unpkg.com vimeo.com; connect-src * \'unsafe-inline\' blob: data:; report-to csp-endpoint; report-uri https://mon-i18n.tiktokv.com/monitor_browser/collect/batch/security/?bid=tiktok_pns&ev_type=csp&revision=90e6d773-21ae-42ab-8c71-39270905f535; upgrade-insecure-requests' + ], + 'feature-policy' => [ + 'microphone \'none\'; geolocation \'none\'' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'strict-transport-security' => [ + 'max-age=31536000; includeSubdomains' + ], + 'x-bytefaas-execution-duration' => [ + '272.82' + ], + 'x-bytefaas-request-id' => [ + '20240610155929068E8F0BBEAB3D57F293' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-gw-dst-psm' => [ + 'serverless.tiktok.desktop' + ], + 'x-ms-token' => [ + 'XDzYsUjpiPqaRgm6u2iqp4-UPewsnALRSAdpwgtMcXn7uR-S1LaEXMVLolhz8fMklz-cHj8mZ4ywnnNuwiG9qoNMKo8ZFk-kYnTvYEKmmfkwBPPWm_yGEvbQBQ==' + ], + 'x-powered-by' => [ + 'Goofy Node' + ], + 'x-pumbaa-web-avail' => [ + '1' + ], + 'x-tt-logid' => [ + '20240610155929068E8F0BBEAB3D57F293' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-tt-trace-host' => [ + '017cfddef21a18b6b0cd798804968dc965f877c995c35dcf874c2202d69a8908ee2099ef630ee94295fa7bfd1e113fbd811c970193a346a9d015f4b5583c13527a8c0bbe68cf1740294ddf56267a3419a5a339d56fbdb5c681a8a43be48a8ca042d07b29c51a09371a2c6540ad303140bb' + ], + 'x-tt-trace-id' => [ + '00-240610155929068E8F0BBEAB3D57F293-3E6828473BEFBE43-00' + ], + 'reporting-endpoints' => [ + 'csp-endpoint="https://mon-i18n.tiktokv.com/monitor_browser/collect/batch/security/?bid=tiktok_pns"' + ], + 'server' => [ + 'TLB' + ], + 'content-encoding' => [ + 'br' + ], + 'x-origin-response-time' => [ + '290,23.46.15.31' + ], + 'x-akamai-request-id' => [ + '1dc6b1c0.2b38a16f' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 15:59:30 GMT' + ], + 'cache-control' => [ + 'max-age=0, no-cache, no-store' + ], + 'pragma' => [ + 'no-cache' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:30 GMT' + ], + 'x-cache' => [ + 'TCP_MISS from a96-16-85-139.deploy.akamaitechnologies.com (AkamaiGHost/11.5.1-56337083) (-)' + ], + 'set-cookie' => [ + 'ttwid=1%7Cj0aXRYSWtaNWx38qJqVUkpKwiy4AYmpg-nvHVOuysFg%7C1718035170%7C86cacb5aa1d30911762f4ac42618b27142002557f096be47f37a0b1d0a3c3fa5; Domain=.tiktok.com; Path=/; Expires=Thu, 05 Jun 2025 15:59:30 GMT; HttpOnly', + 'tt_csrf_token=XHV4LExw-mfjYI5aFnSQ3S4WCQjoDEFngTos; path=/; domain=.tiktok.com; samesite=lax; secure; httponly', + 'tt_chain_token=dV4Ot+x2FaWphIoq1+P2fQ==; path=/; expires=Sat, 07 Dec 2024 15:59:30 GMT; domain=.tiktok.com; secure; httponly', + 'msToken=XDzYsUjpiPqaRgm6u2iqp4-UPewsnALRSAdpwgtMcXn7uR-S1LaEXMVLolhz8fMklz-cHj8mZ4ywnnNuwiG9qoNMKo8ZFk-kYnTvYEKmmfkwBPPWm_yGEvbQBQ==; Path=/; Expires=Thu, 20 Jun 2024 15:59:30 GMT; Secure; SameSite=None', + 'ak_bmsc=973A9895782688909F8CE463A1E6F3C1~000000000000000000000000000000~YAAQi1UQYFBM4/uPAQAAU0bgAhgiO43zwghK4QiQ9npGWlTbQSCEN/3I38WNGVa3YYrzbHO96WxDfXQoX8mhDV4MEhqy/c3GolfQxTWFxgO8IpF6JV4duAw4OHistmS6MXehI0QPI6wtDDmMUL6aNxOfIE2uUQQ43cx3xuOFKV9zhDBjIg+YNqUCu4uf0KO+FcUGFwCUuDn3XXMIQQtb7F2CSr0Bb7tme6rr6kE69IMPV9QLC4qyICqokS9z+nx5G/HvGTguMPZHHHACTOWl9O21+JdgkJF2HzJlgqn/Xk3/1V3UXm7CTkdJllUrlJ1csdj5kbK9+/ymkyITINvXT9xmIBYI+nbgalsDZ+fCF5EOlmN9ido0beuUizX8PiglHRq5aPD4f62YsA==; Domain=.tiktok.com; Path=/; Expires=Mon, 10 Jun 2024 17:59:30 GMT; Max-Age=7200' + ], + 'x-cache-remote' => [ + 'TCP_MISS from a23-46-15-31.deploy.akamaitechnologies.com (AkamaiGHost/11.5.2-56655770) (-)' + ], + 'x-tt-trace-tag' => [ + 'id=16;cdn-cache=miss;type=dyn' + ], + 'server-timing' => [ + 'cdn-cache; desc=MISS, edge; dur=101, origin; dur=290', + 'inner; dur=285' + ], + 'x-parent-response-time' => [ + '391,96.16.85.139' + ], + 'Content-Location' => [ + 'https://www.tiktok.com/@a3noticias/video/6806030056956251397' + ], + 'X-Request-Time' => [ + '0.477 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'TikTok - Make Your Day
' +]; diff --git a/tests/cache/www.tiktok.com.oembed.901352644d63ef08f7546c3394cf07bb.php b/tests/cache/www.tiktok.com.oembed.901352644d63ef08f7546c3394cf07bb.php new file mode 100644 index 00000000..f704d0e4 --- /dev/null +++ b/tests/cache/www.tiktok.com.oembed.901352644d63ef08f7546c3394cf07bb.php @@ -0,0 +1,86 @@ + [ + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'x-tt-logid' => [ + '2024061015593069332DF90B98E956EB3E' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-download-options' => [ + 'noopen' + ], + 'x-tt-trace-host' => [ + '017cfddef21a18b6b0cd798804968dc965f877c995c35dcf874c2202d69a8908eeebb4e2f87ba4ba048cc68cf8c5fb9a8a79fd479e917deeb9040c39919715a622b322fa62feeaa713b1b25990f5dbd7eec6c8d770fe1b0f27b5d0a11795c6cbb0dc22c4407475d9a4c1b176f2daba109c' + ], + 'x-tt-trace-id' => [ + '00-24061015593069332DF90B98E956EB3E-097BE6D33889413E-00' + ], + 'server' => [ + 'TLB' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'content-encoding' => [ + 'br' + ], + 'content-length' => [ + '659' + ], + 'x-origin-response-time' => [ + '149,23.46.15.38' + ], + 'x-akamai-request-id' => [ + '6a10d4b.2b38b36d' + ], + 'expires' => [ + 'Mon, 10 Jun 2024 15:59:31 GMT' + ], + 'cache-control' => [ + 'max-age=0, no-cache, no-store' + ], + 'pragma' => [ + 'no-cache' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:31 GMT' + ], + 'x-cache' => [ + 'TCP_MISS from a96-16-85-139.deploy.akamaitechnologies.com (AkamaiGHost/11.5.1-56337083) (-)' + ], + 'x-cache-remote' => [ + 'TCP_MISS from a23-46-15-38.deploy.akamaitechnologies.com (AkamaiGHost/11.5.1-56337083) (-)' + ], + 'x-tt-trace-tag' => [ + 'id=16;cdn-cache=miss;type=dyn' + ], + 'server-timing' => [ + 'cdn-cache; desc=MISS, edge; dur=100, origin; dur=149', + 'inner; dur=139' + ], + 'x-parent-response-time' => [ + '248,96.16.85.139' + ], + 'Content-Location' => [ + 'https://www.tiktok.com/oembed?url=https%3A%2F%2Fwww.tiktok.com%2F%40a3noticias%2Fvideo%2F6806030056956251397&format=json' + ], + 'X-Request-Time' => [ + '0.316 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","type":"video","title":"Nuestro #AplausoSanitario más sincero. Para todos. Y recuerda, #QuédateEnCasa","author_url":"https://www.tiktok.com/@a3noticias","author_name":"Antena 3 Noticias","width":"100%","height":"100%","html":"
@a3noticias

Nuestro #AplausoSanitario más sincero. Para todos. Y recuerda, #QuédateEnCasa

♬ Resistiré - Duo Dinamico
","thumbnail_width":480,"thumbnail_height":848,"thumbnail_url":"https://p77-sign-va.tiktokcdn.com/obj/tos-maliva-p-0068/165175e006354d838501378cfb325b79_1584652367?x-expires=1718204400&x-signature=weANzY8AXzX93c5j7jm34neMhWY%3D","provider_url":"https://www.tiktok.com/","provider_name":"TikTok","author_unique_id":"a3noticias","embed_product_id":"6806030056956251397","embed_type":"video"}' +]; diff --git a/tests/cache/www.tumblr.com.oembed-1.0.1069794d66a738c0f11667124fb2b5e0.php b/tests/cache/www.tumblr.com.oembed-1.0.1069794d66a738c0f11667124fb2b5e0.php new file mode 100644 index 00000000..909ac09f --- /dev/null +++ b/tests/cache/www.tumblr.com.oembed-1.0.1069794d66a738c0f11667124fb2b5e0.php @@ -0,0 +1,64 @@ + [ + 'server' => [ + 'nginx' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:58:59 GMT' + ], + 'content-type' => [ + 'application/json; charset=utf-8' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'x-rid' => [ + 'b7feab114b7ceae733461276601efde2' + ], + 'p3p' => [ + 'CP="Tumblr\'s privacy policy is available here: https://www.tumblr.com/policy/en/privacy"' + ], + 'x-frame-options' => [ + 'deny' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'referrer-policy' => [ + 'origin-when-cross-origin' + ], + 'content-security-policy' => [ + 'script-src \'self\' https://assets.tumblr.com https://sb.scorecardresearch.com/beacon.js https://ssl.google-analytics.com/ga.js https://www.google-analytics.com/analytics.js https://fc.yahoo.com/sdarla/php/client.php https://s.yimg.com/rq/darla/ https://www.googletagservices.com/tag/js/gpt.js https://securepubads.g.doubleclick.net/gpt/ https://securepubads.g.doubleclick.net/gampad/ads https://pagead2.googlesyndication.com/pagead/osd.js https://www.google.com/recaptcha/api.js https://*.gemini.yahoo.com https://s.yimg.com/av/gemini/ga/gemini-iframe.js https://s.yimg.com/av/curveball/ \'unsafe-eval\' \'nonce-etGQr5EgPFYIXCq168Qp1O9os\'; object-src \'none\'; worker-src blob:; base-uri \'self\'; report-uri https://www.tumblr.com/svc/cspreports;' + ], + 'x-ua-compatible' => [ + 'IE=Edge,chrome=1' + ], + 'content-encoding' => [ + 'br' + ], + 'strict-transport-security' => [ + 'max-age=31536000; preload' + ], + 'x-nc' => [ + 'BYPASS mad 1' + ], + 'alt-svc' => [ + 'h3=":443"; ma=86400' + ], + 'Content-Location' => [ + 'https://www.tumblr.com/oembed/1.0?url=https%3A%2F%2Fhe-who-photographs-rather-ok.tumblr.com%2Fpost%2F165326273724' + ], + 'X-Request-Time' => [ + '0.172 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"cache_age":3600,"url":"https://www.tumblr.com/he-who-photographs-rather-ok/165326273724","provider_url":"https://www.tumblr.com/","provider_name":"Tumblr","author_name":"He-who-photographs-rather-OK","version":"1.0","author_url":"https://www.tumblr.com/he-who-photographs-rather-ok","type":"rich","html":"","height":null,"width":540}' +]; diff --git a/tests/cache/www.twitch.tv.twit.php b/tests/cache/www.twitch.tv.twit.php new file mode 100644 index 00000000..2e4284fb --- /dev/null +++ b/tests/cache/www.twitch.tv.twit.php @@ -0,0 +1,55 @@ + [ + 'connection' => [ + 'keep-alive' + ], + 'content-type' => [ + 'text/html' + ], + 'content-encoding' => [ + 'br' + ], + 'set-cookie' => [ + 'server_session_id=d0fb05a1476744cbb783139eaf5e3026; domain=.twitch.tv; path=/; secure; samesite=none', + 'unique_id=DKTHSTLUlYf6vKlO1iZ3ZnMlkcKKTmiy; expires=Wed, 04 May 2022 15:22:39 GMT; domain=.twitch.tv; path=/; secure; samesite=none', + 'unique_id_durable=DKTHSTLUlYf6vKlO1iZ3ZnMlkcKKTmiy; expires=Wed, 04 May 2022 15:22:39 GMT; domain=.twitch.tv; path=/; secure; samesite=none; httponly', + 'twitch.lohp.countryCode=ES; domain=.twitch.tv; expires=Fri, 29 Apr 2022 15:22:39 GMT;' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'cache-control' => [ + 'private, max-age=0' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:39 GMT' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'Content-Location' => [ + 'https://www.twitch.tv/twit' + ], + 'X-Request-Time' => [ + '0.110 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Twitch
' +]; diff --git a/tests/cache/www.twitch.tv.videos-106400740.php b/tests/cache/www.twitch.tv.videos-106400740.php new file mode 100644 index 00000000..d2fa96f3 --- /dev/null +++ b/tests/cache/www.twitch.tv.videos-106400740.php @@ -0,0 +1,55 @@ + [ + 'connection' => [ + 'keep-alive' + ], + 'content-type' => [ + 'text/html' + ], + 'content-encoding' => [ + 'br' + ], + 'set-cookie' => [ + 'server_session_id=907201d6a5704bbc855fead0126a54dc; domain=.twitch.tv; path=/; secure; samesite=none', + 'unique_id=i8fj3PUGo6ZPgPNQcMjUEuVlNVvv7I8n; expires=Wed, 04 May 2022 15:21:59 GMT; domain=.twitch.tv; path=/; secure; samesite=none', + 'unique_id_durable=i8fj3PUGo6ZPgPNQcMjUEuVlNVvv7I8n; expires=Wed, 04 May 2022 15:21:59 GMT; domain=.twitch.tv; path=/; secure; samesite=none; httponly', + 'twitch.lohp.countryCode=ES; domain=.twitch.tv; expires=Fri, 29 Apr 2022 15:21:59 GMT;' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'cache-control' => [ + 'private, max-age=0' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:21:59 GMT' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'Content-Location' => [ + 'https://www.twitch.tv/videos/106400740' + ], + 'X-Request-Time' => [ + '0.106 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Twitch
' +]; diff --git a/tests/cache/www.twitch.tv.videos-72749628.php b/tests/cache/www.twitch.tv.videos-72749628.php new file mode 100644 index 00000000..6e6e354d --- /dev/null +++ b/tests/cache/www.twitch.tv.videos-72749628.php @@ -0,0 +1,55 @@ + [ + 'connection' => [ + 'keep-alive' + ], + 'content-type' => [ + 'text/html' + ], + 'content-encoding' => [ + 'br' + ], + 'set-cookie' => [ + 'server_session_id=72ad548139eb45ca9fc9d280fd2b6f92; domain=.twitch.tv; path=/; secure; samesite=none', + 'unique_id=a4KZS4cz2uwpOfLJnIScHsglvSNiH62x; expires=Thu, 10 Jul 2025 15:59:28 GMT; domain=.twitch.tv; path=/; secure; samesite=none', + 'unique_id_durable=a4KZS4cz2uwpOfLJnIScHsglvSNiH62x; expires=Thu, 10 Jul 2025 15:59:28 GMT; domain=.twitch.tv; path=/; secure; samesite=none; httponly', + 'twitch.lohp.countryCode=ES; domain=.twitch.tv; path=/; expires=Sat, 05 Jul 2025 15:59:28 GMT;' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'cache-control' => [ + 'private, max-age=0' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:28 GMT' + ], + 'vary' => [ + 'Accept-Encoding' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'Content-Location' => [ + 'https://www.twitch.tv/videos/72749628' + ], + 'X-Request-Time' => [ + '0.572 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Twitch
' +]; diff --git a/tests/cache/www.ustream.tv.channel-red-shoes-billiards-60803-camera-1.php b/tests/cache/www.ustream.tv.channel-red-shoes-billiards-60803-camera-1.php new file mode 100644 index 00000000..3cc1cda3 --- /dev/null +++ b/tests/cache/www.ustream.tv.channel-red-shoes-billiards-60803-camera-1.php @@ -0,0 +1,578 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:00 GMT' + ], + 'server' => [ + 'ustream/web' + ], + 'server-timing' => [ + 'intid;desc=d46455820242f382' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-xss-protection' => [ + '1; mode=block' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'x-framework-lang' => [ + 'es_ES' + ], + 'x-rsrc' => [ + 'sjc04-ustream-web10' + ], + 'content-type' => [ + 'text/html; charset=UTF-8' + ], + 'x-backendorigin' => [ + 'www-web-bck/sjc04-ustream-web10', + 'www.ustream.tv-bck/dal09-web-cache02' + ], + 'age' => [ + '0' + ], + 'x-domain' => [ + 'www.ustream.tv' + ], + 'x-cache' => [ + 'MISS' + ], + 'transfer-encoding' => [ + 'chunked' + ], + 'Content-Location' => [ + 'http://www.ustream.tv/channel/red-shoes-billiards-60803-camera-1' + ], + 'X-Request-Time' => [ + '0.835 ms' + ] + ], + 'statusCode' => 404, + 'reasonPhrase' => 'Not Found', + 'body' => ' + + + Streaming Video Platform & Hosting Services + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+

+ 404 error
+ Sorry, the page you requested cannot be found.

+ +

Useful Links:

+ + +

If you came here while trying to watch a video or live stream, please contact the broadcaster or publisher.

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + ' +]; diff --git a/tests/cache/www.ustream.tv.oembed.d71a254715924dacfa569f63e50969a8.php b/tests/cache/www.ustream.tv.oembed.d71a254715924dacfa569f63e50969a8.php new file mode 100644 index 00000000..f2a308d1 --- /dev/null +++ b/tests/cache/www.ustream.tv.oembed.d71a254715924dacfa569f63e50969a8.php @@ -0,0 +1,88 @@ + [ + 'date' => [ + 'Mon, 10 Jun 2024 15:59:01 GMT', + 'Mon, 10 Jun 2024 15:59:02 GMT' + ], + 'server' => [ + 'ustream/web', + 'ustream/web' + ], + 'server-timing' => [ + 'intid;desc=96505c865d7ad688', + 'intid;desc=8293007af9cb0774' + ], + 'location' => [ + 'https://video.ibm.com/oembed?url=http%3A%2F%2Fwww.ustream.tv%2Fchannel%2Fred-shoes-billiards-60803-camera-1&format=json' + ], + 'x-rsrc' => [ + 'sjc03-ustream-web12', + 'sjc04-ustream-web09' + ], + 'content-length' => [ + '0', + '882' + ], + 'content-type' => [ + 'text/html; charset=UTF-8', + 'application/json; charset=UTF-8' + ], + 'x-backendorigin' => [ + 'www-web-bck/sjc03-ustream-web12', + 'www.ustream.tv-bck/dal09-web-cache01 HTTP/1.1 200 OK', + 'www-web-bck/sjc04-ustream-web09', + 'www.ustream.tv-bck/sjc03-web-cache08' + ], + 'age' => [ + '0', + '0' + ], + 'x-domain' => [ + 'www.ustream.tv', + 'video.ibm.com' + ], + 'x-cache' => [ + 'MISS', + 'MISS' + ], + 'set-cookie' => [ + 'PHPSESSID=UstreamGuestSession; path=/; secure; HttpOnly' + ], + 'expires' => [ + 'Thu, 19 Nov 1981 08:52:00 GMT' + ], + 'cache-control' => [ + 'public, max-age=600' + ], + 'pragma' => [ + 'no-cache' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'referrer-policy' => [ + 'strict-origin-when-cross-origin' + ], + 'x-framework-lang' => [ + 'es_ES' + ], + 'accept-ranges' => [ + 'bytes' + ], + 'Content-Location' => [ + 'https://video.ibm.com/oembed?url=http%3A%2F%2Fwww.ustream.tv%2Fchannel%2Fred-shoes-billiards-60803-camera-1&format=json' + ], + 'X-Request-Time' => [ + '1.760 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"provider_url":"http:\\/\\/www.ustream.tv\\/","html":"
Skip to main content

WIRED

China Rolls Out Its First Talent Visa as the US Retreats on H-1Bs
Made in China

China Rolls Out Its First Talent Visa as the US Retreats on H-1Bs

The Chinese government unveiled a program to woo foreign talent just as the US cracked down on H-1Bs with a $100,000 fee. The move immediately provoked xenophobic backlash.
Chatbots Play With Your Emotions to Avoid Saying Goodbye
The Post-Chuck Schumer Era
OpenAI Is Preparing to Launch a Social App for AI-Generated Videos
Broadcast TV Is a 'Melting Ice Cube.’ Kimmel Just Turned Up the Heat
WIRED Takes You Back to School
Generation iPad

WIRED Takes You Back to School

Young people entering classrooms this fall need a totally different tool set than the generations before them.
The New Era of Work Travel
Are We Healthy Yet?
Beyond Wellness

Are We Healthy Yet?

How to Win a Fight
Special Edition

How to Win a Fight

You're Not Ready
Special Edition

You're Not Ready

Geek Power: Steven Levy Revisits Tech Titans, Hackers, Idealists
Master Minds

Geek Power: Steven Levy Revisits Tech Titans, Hackers, Idealists

Originally published April 2010: In 1984, Hackers chronicled the coders, visionaries, and hygiene-challenged nerds who were hatching our digital world. Now the author circles back with them—and checks in with the next generation.
Online Dating Made This Woman a Pawn in a Global Crime Plot
The Battle for the Soul of Buy Nothing
Adoption Moved to Facebook and a War Began
Going Dumb: My Year With a Flip Phone
' +]; diff --git a/tests/cache/www.wired.com.wp-json-oembed-1.0-embed.f979e136668a2b1f8801a26690847913.php b/tests/cache/www.wired.com.wp-json-oembed-1.0-embed.f979e136668a2b1f8801a26690847913.php new file mode 100644 index 00000000..029468bd --- /dev/null +++ b/tests/cache/www.wired.com.wp-json-oembed-1.0-embed.f979e136668a2b1f8801a26690847913.php @@ -0,0 +1,104 @@ + [ + 'access-control-allow-headers' => [ + 'Authorization' + ], + 'access-control-allow-origin' => [ + '*' + ], + 'access-control-expose-headers' => [ + 'X-WP-Total, X-WP-TotalPages' + ], + 'allow' => [ + 'GET' + ], + 'content-type' => [ + 'application/json; charset=UTF-8' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'x-robots-tag' => [ + 'noindex' + ], + 'verso' => [ + 'false' + ], + 'accept-ranges' => [ + 'none' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:20:01 GMT' + ], + 'via' => [ + '1.1 varnish' + ], + 'age' => [ + '465' + ], + 'cache-control' => [ + 'no-cache' + ], + 'set-cookie' => [ + 'pay_ent_smp=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsInZlciI6MX0.eyJ1cmxzIjpbXSwiY250IjowLCJtYXgiOjQsImV4cCI6MjAyMTA0fQ.Zb-TlJeIXb3ZmGBKgqLyxTrlPPfw4rtxVUdU0T39e4M; Path=/; Expires=Mon, 04 Apr 2022 21:20:01 GMT; Domain=wired.com; Secure;', + 'pay_events=grant-new-smp; Max-Age=20; SameSite=Strict; Secure;', + 'CN_xid=a0325b0a-e616-4f0f-8672-0f400bbf8e4b; Expires=Fri, 01 Oct 2021 15:20:01 GMT; Domain=.wired.com; path=/; Secure; SameSite=None;', + 'CN_xid_refresh=a0325b0a-e616-4f0f-8672-0f400bbf8e4b; Expires=Wed, 02 Apr 2031 15:20:01 GMT; Domain=.wired.com; path=/; Secure; httponly; SameSite=None;', + 'xid1=1; Expires=Sun, 04 Apr 2021 15:20:16 GMT; path=/;', + 'CN_segments=co.w2113; Expires=Fri, 01 Oct 2021 15:20:01 GMT; path=/;', + 'verso_bucket=696; Expires=Mon, 04 Apr 2022 15:20:01 GMT; path=/;', + 'CN_geo_country_code=ES; Expires=Fri, 01 Oct 2021 15:20:01 GMT; Path=/; Domain=wired.com; Samesite=None; Secure' + ], + 'apple-news-services-host' => [ + 'www.wired.com' + ], + 'apple-news-services-request-url' => [ + '/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.wired.com%2F2016%2F07%2Freview-yi-4k-action-camera%2F' + ], + 'apple-news-services-parsed-url' => [ + '/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.wired.com%2F2016%2F07%2Freview-yi-4k-action-camera%2F' + ], + 'apple-news-services-handled' => [ + 'false' + ], + 'content-security-policy' => [ + 'default-src https: data: \'unsafe-inline\' \'unsafe-eval\'; child-src https: data: blob:; connect-src https: data: blob: wss://*.hotjar.com; font-src https: data:; img-src https: blob: data: android-webview-video-poster:; media-src blob: data: https:; object-src https:; script-src https: data: blob: \'unsafe-inline\' \'unsafe-eval\'; style-src https: \'unsafe-inline\'; block-all-mixed-content; upgrade-insecure-requests;' + ], + 'strict-transport-security' => [ + 'max-age=31536000; preload' + ], + 'x-served-by' => [ + 'cache-mad22063-MAD' + ], + 'x-cache' => [ + 'HIT' + ], + 'x-cache-hits' => [ + '1' + ], + 'x-timer' => [ + 'S1617549602.700250,VS0,VE1' + ], + 'x-ua-device' => [ + 'desktop' + ], + 'vary' => [ + 'accept-payment, Verso, accept-encoding' + ], + 'content-encoding' => [ + 'br' + ], + 'Content-Location' => [ + 'https://www.wired.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.wired.com%2F2016%2F07%2Freview-yi-4k-action-camera%2F' + ], + 'X-Request-Time' => [ + '0.112 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"version":"1.0","provider_name":"WIRED","provider_url":"https:\\/\\/www.wired.com","author_name":"Wired Staff","author_url":"https:\\/\\/www.wired.com\\/author\\/wired-staff\\/","title":"Review: Yi 4K Action Camera","type":"rich","width":600,"height":338,"html":"
Review: Yi 4K Action Camera<\\/a><\\/blockquote>\\nAntes de ir a YouTube
YouTube una empresa de Google

Antes de ir a YouTube

En Google utilizamos cookies y datos para:
  • Proporcionar y mantener servicios, como hacer un seguimiento de las interrupciones y prevenir el spam, el fraude y los abusos
  • Medir la interacción de la audiencia y estadísticas de los sitios web para entender cómo se utilizan nuestros servicios
Si aceptas, también usaremos las cookies y los datos para:
  • Mejorar la calidad de nuestros servicios y desarrollar otros nuevos
  • Mostrar anuncios y medir su eficacia
  • Mostrar contenido personalizado en función de tus ajustes
  • Mostrar anuncios genéricos o personalizados, en función de tus ajustes, en Google y en la Web
Con respecto al contenido y los anuncios no personalizados, lo que veas puede estar influido por factores como lo que estés viendo en ese momento y tu ubicación (el servicio de anuncios se basa en la ubicación general). El contenido y los anuncios personalizados se pueden basar, además de en esos criterios, en tu actividad, como las búsquedas que hagas en Google y los vídeos que veas en YouTube. Los anuncios y el contenido personalizados incluyen, entre otras cosas, resultados y recomendaciones más relevantes, una página de inicio de YouTube personalizada y anuncios adaptados a tus intereses.

Haz clic en Personalizar para ver las opciones disponibles, como los controles que permiten rechazar el uso de cookies para la personalización e información sobre los controles del navegador que permiten rechazar parte o la totalidad de las cookies para otros usos. También puedes visitar g.co/privacytools en cualquier momento.

' +]; diff --git a/tests/cache/www.youtube.com.oembed.44a61a3c2dd08c4b95475fbaf4d23362.php b/tests/cache/www.youtube.com.oembed.44a61a3c2dd08c4b95475fbaf4d23362.php new file mode 100644 index 00000000..c4fb89ac --- /dev/null +++ b/tests/cache/www.youtube.com.oembed.44a61a3c2dd08c4b95475fbaf4d23362.php @@ -0,0 +1,51 @@ + [ + 'content-type' => [ + 'application/json' + ], + 'vary' => [ + 'Origin', + 'X-Origin', + 'Referer' + ], + 'content-encoding' => [ + 'gzip' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:40 GMT' + ], + 'server' => [ + 'scaffolding on HTTPServer2' + ], + 'cache-control' => [ + 'private' + ], + 'content-length' => [ + '408' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://www.youtube.com/oembed?url=https%3A%2F%2Fwww.youtube.com%2Fplaylist%3Flist%3DPL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST&format=json' + ], + 'X-Request-Time' => [ + '0.136 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"title":"De espaldas al patriarcado","author_name":"Scadrei5","author_url":"/user/Scadrei5","type":"video","height":113,"width":200,"version":"1.0","provider_name":"YouTube","provider_url":"https://www.youtube.com/","thumbnail_height":360,"thumbnail_width":480,"thumbnail_url":"https://i.ytimg.com/vi/CdbnVwot6lc/hqdefault.jpg","html":"\\u003ciframe width=\\u0022200\\u0022 height=\\u0022113\\u0022 src=\\u0022https://www.youtube.com/embed/videoseries?list=PL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST\\u0022 frameborder=\\u00220\\u0022 allow=\\u0022accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\\u0022 allowfullscreen\\u003e\\u003c/iframe\\u003e"}' +]; diff --git a/tests/cache/www.youtube.com.oembed.4e2dd395e94cc4f7fd39a8081b0cdc17.php b/tests/cache/www.youtube.com.oembed.4e2dd395e94cc4f7fd39a8081b0cdc17.php new file mode 100644 index 00000000..5f078b9c --- /dev/null +++ b/tests/cache/www.youtube.com.oembed.4e2dd395e94cc4f7fd39a8081b0cdc17.php @@ -0,0 +1,51 @@ + [ + 'content-type' => [ + 'application/json' + ], + 'vary' => [ + 'Origin', + 'X-Origin', + 'Referer' + ], + 'content-encoding' => [ + 'gzip' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:32 GMT' + ], + 'server' => [ + 'scaffolding on HTTPServer2' + ], + 'cache-control' => [ + 'private' + ], + 'content-length' => [ + '420' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000' + ], + 'Content-Location' => [ + 'https://www.youtube.com/oembed?format=json&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeiHXASgRTcA' + ], + 'X-Request-Time' => [ + '0.197 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"title":"Noisy kittens waiting for dinner!","author_name":"smshdchrb","author_url":"https://www.youtube.com/@smshdchrb","type":"video","height":150,"width":200,"version":"1.0","provider_name":"YouTube","provider_url":"https://www.youtube.com/","thumbnail_height":360,"thumbnail_width":480,"thumbnail_url":"https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg","html":"\\u003ciframe width=\\u0022200\\u0022 height=\\u0022150\\u0022 src=\\u0022https://www.youtube.com/embed/eiHXASgRTcA?feature=oembed\\u0022 frameborder=\\u00220\\u0022 allow=\\u0022accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\\u0022 referrerpolicy=\\u0022strict-origin-when-cross-origin\\u0022 allowfullscreen title=\\u0022Noisy kittens waiting for dinner!\\u0022\\u003e\\u003c/iframe\\u003e"}' +]; diff --git a/tests/cache/www.youtube.com.oembed.5983a98476444a059f7de5f74a874179.php b/tests/cache/www.youtube.com.oembed.5983a98476444a059f7de5f74a874179.php new file mode 100644 index 00000000..1912a6f4 --- /dev/null +++ b/tests/cache/www.youtube.com.oembed.5983a98476444a059f7de5f74a874179.php @@ -0,0 +1,51 @@ + [ + 'content-type' => [ + 'application/json' + ], + 'vary' => [ + 'Origin', + 'X-Origin', + 'Referer' + ], + 'content-encoding' => [ + 'gzip' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:06 GMT' + ], + 'server' => [ + 'scaffolding on HTTPServer2' + ], + 'cache-control' => [ + 'private' + ], + 'content-length' => [ + '378' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://www.youtube.com/oembed?url=http%3A%2F%2Fyoutu.be%2FeiHXASgRTcA&format=json' + ], + 'X-Request-Time' => [ + '0.114 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"title":"Noisy kittens waiting for dinner!","author_name":"smshdchrb","author_url":"https://www.youtube.com/user/smshdchrb","type":"video","height":150,"width":200,"version":"1.0","provider_name":"YouTube","provider_url":"https://www.youtube.com/","thumbnail_height":360,"thumbnail_width":480,"thumbnail_url":"https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg","html":"\\u003ciframe width=\\u0022200\\u0022 height=\\u0022150\\u0022 src=\\u0022https://www.youtube.com/embed/eiHXASgRTcA?feature=oembed\\u0022 frameborder=\\u00220\\u0022 allow=\\u0022accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\\u0022 allowfullscreen\\u003e\\u003c/iframe\\u003e"}' +]; diff --git a/tests/cache/www.youtube.com.oembed.8ce1ccae073d71579a2aacd9427c391b.php b/tests/cache/www.youtube.com.oembed.8ce1ccae073d71579a2aacd9427c391b.php new file mode 100644 index 00000000..d4825858 --- /dev/null +++ b/tests/cache/www.youtube.com.oembed.8ce1ccae073d71579a2aacd9427c391b.php @@ -0,0 +1,51 @@ + [ + 'content-type' => [ + 'application/json' + ], + 'vary' => [ + 'Origin', + 'X-Origin', + 'Referer' + ], + 'content-encoding' => [ + 'gzip' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:20:51 GMT' + ], + 'server' => [ + 'scaffolding on HTTPServer2' + ], + 'cache-control' => [ + 'private' + ], + 'content-length' => [ + '378' + ], + 'x-xss-protection' => [ + '0' + ], + 'x-frame-options' => [ + 'SAMEORIGIN' + ], + 'x-content-type-options' => [ + 'nosniff' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'Content-Location' => [ + 'https://www.youtube.com/oembed?url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeiHXASgRTcA&format=json' + ], + 'X-Request-Time' => [ + '0.133 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => '{"title":"Noisy kittens waiting for dinner!","author_name":"smshdchrb","author_url":"https://www.youtube.com/user/smshdchrb","type":"video","height":150,"width":200,"version":"1.0","provider_name":"YouTube","provider_url":"https://www.youtube.com/","thumbnail_height":360,"thumbnail_width":480,"thumbnail_url":"https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg","html":"\\u003ciframe width=\\u0022200\\u0022 height=\\u0022150\\u0022 src=\\u0022https://www.youtube.com/embed/eiHXASgRTcA?feature=oembed\\u0022 frameborder=\\u00220\\u0022 allow=\\u0022accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\\u0022 allowfullscreen\\u003e\\u003c/iframe\\u003e"}' +]; diff --git a/tests/cache/www.youtube.com.playlist.13d1655ccf6cbdc1fc0162c6a02f822a.php b/tests/cache/www.youtube.com.playlist.13d1655ccf6cbdc1fc0162c6a02f822a.php new file mode 100644 index 00000000..9da375d3 --- /dev/null +++ b/tests/cache/www.youtube.com.playlist.13d1655ccf6cbdc1fc0162c6a02f822a.php @@ -0,0 +1,1154 @@ + [ + 'content-type' => [ + 'application/binary', + 'text/html; charset=utf-8' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate', + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache', + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT', + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:40 GMT', + 'Sun, 04 Apr 2021 15:22:40 GMT' + ], + 'location' => [ + 'https://consent.youtube.com/m?continue=https%3A%2F%2Fwww.youtube.com%2Fplaylist%3Flist%3DPL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST&gl=ES&m=0&pc=yt&uxe=23983172&hl=es&src=1' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'server' => [ + 'ESF', + 'ESF' + ], + 'content-length' => [ + '0' + ], + 'x-xss-protection' => [ + '0', + '0' + ], + 'set-cookie' => [ + 'CONSENT=PENDING+552; expires=Fri, 01-Jan-2038 00:00:00 GMT; path=/; domain=.youtube.com' + ], + 'p3p' => [ + 'CP="This is not a P3P policy! See g.co/p3phelp for more info."' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43" HTTP/2 200', + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'vary' => [ + 'Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site' + ], + 'x-ua-compatible' => [ + 'IE=edge' + ], + 'cross-origin-resource-policy' => [ + 'same-site' + ], + 'content-security-policy' => [ + 'script-src \'nonce-DKQWx6/nKFBQ7gsjj92gFg\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/ConsentUi/cspreport;worker-src \'self\'', + 'script-src \'nonce-DKQWx6/nKFBQ7gsjj92gFg\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/ConsentUi/cspreport' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://consent.youtube.com/m?continue=https%3A%2F%2Fwww.youtube.com%2Fplaylist%3Flist%3DPL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST&gl=ES&m=0&pc=yt&uxe=23983172&hl=es&src=1' + ], + 'X-Request-Time' => [ + '0.338 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Antes de ir a YouTube
YouTube una empresa de Google

Antes de ir a YouTube

En Google utilizamos cookies y datos para:
  • Proporcionar y mantener servicios, como hacer un seguimiento de las interrupciones y prevenir el spam, el fraude y los abusos
  • Medir la interacción de la audiencia y estadísticas de los sitios web para entender cómo se utilizan nuestros servicios
Si aceptas, también usaremos las cookies y los datos para:
  • Mejorar la calidad de nuestros servicios y desarrollar otros nuevos
  • Mostrar anuncios y medir su eficacia
  • Mostrar contenido personalizado en función de tus ajustes
  • Mostrar anuncios genéricos o personalizados, en función de tus ajustes, en Google y en la Web
Con respecto al contenido y los anuncios no personalizados, lo que veas puede estar influido por factores como lo que estés viendo en ese momento y tu ubicación (el servicio de anuncios se basa en la ubicación general). El contenido y los anuncios personalizados se pueden basar, además de en esos criterios, en tu actividad, como las búsquedas que hagas en Google y los vídeos que veas en YouTube. Los anuncios y el contenido personalizados incluyen, entre otras cosas, resultados y recomendaciones más relevantes, una página de inicio de YouTube personalizada y anuncios adaptados a tus intereses.

Haz clic en Personalizar para ver las opciones disponibles, como los controles que permiten rechazar el uso de cookies para la personalización e información sobre los controles del navegador que permiten rechazar parte o la totalidad de las cookies para otros usos. También puedes visitar g.co/privacytools en cualquier momento.

' +]; diff --git a/tests/cache/www.youtube.com.watch.878f5352b6f0e632a763ebf05fb48b16.php b/tests/cache/www.youtube.com.watch.878f5352b6f0e632a763ebf05fb48b16.php new file mode 100644 index 00000000..63400706 --- /dev/null +++ b/tests/cache/www.youtube.com.watch.878f5352b6f0e632a763ebf05fb48b16.php @@ -0,0 +1,178 @@ + [ + 'content-type' => [ + 'application/binary', + 'text/html; charset=utf-8' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate', + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache', + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT', + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Mon, 10 Jun 2024 15:59:31 GMT', + 'Mon, 10 Jun 2024 15:59:31 GMT' + ], + 'location' => [ + 'https://www.youtube.com/watch?v=eiHXASgRTcA' + ], + 'server' => [ + 'ESF', + 'ESF' + ], + 'content-length' => [ + '0' + ], + 'x-xss-protection' => [ + '0', + '0' + ], + 'x-frame-options' => [ + 'SAMEORIGIN HTTP/2 200', + 'SAMEORIGIN' + ], + 'strict-transport-security' => [ + 'max-age=31536000' + ], + 'origin-trial' => [ + 'AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9' + ], + 'cross-origin-opener-policy' => [ + 'same-origin-allow-popups; report-to="youtube_main"' + ], + 'permissions-policy' => [ + 'ch-ua-arch=*, ch-ua-bitness=*, ch-ua-full-version=*, ch-ua-full-version-list=*, ch-ua-model=*, ch-ua-wow64=*, ch-ua-form-factor=*, ch-ua-platform=*, ch-ua-platform-version=*' + ], + 'report-to' => [ + '{"group":"youtube_main","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/youtube_main"}]}' + ], + 'p3p' => [ + 'CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=es for more info."' + ], + 'content-encoding' => [ + 'br' + ], + 'set-cookie' => [ + 'YSC=GfQrNwSbRio; Domain=.youtube.com; Path=/; Secure; HttpOnly; SameSite=none', + '__Secure-YEC=CgtsR3oxenMydlVUQSjjxZyzBjIhCgJFUxIbEhcSFRMLFBUWFwwYGRobHB0eHw4PIBAREiA_; Domain=.youtube.com; Expires=Thu, 10-Jul-2025 15:59:30 GMT; Path=/; Secure; HttpOnly; SameSite=lax', + 'VISITOR_PRIVACY_METADATA=CgJFUxIbEhcSFRMLFBUWFwwYGRobHB0eHw4PIBAREiA_; Domain=.youtube.com; Expires=Thu, 10-Jul-2025 15:59:31 GMT; Path=/; Secure; HttpOnly; SameSite=none', + 'VISITOR_INFO1_LIVE=; Domain=.youtube.com; Expires=Tue, 14-Sep-2021 15:59:31 GMT; Path=/; Secure; HttpOnly; SameSite=none' + ], + 'alt-svc' => [ + 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000' + ], + 'Content-Location' => [ + 'https://www.youtube.com/watch?v=eiHXASgRTcA' + ], + 'X-Request-Time' => [ + '0.804 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Noisy kittens waiting for dinner! - YouTube
InformaciónPrensaDerechos de autorContactarCreadoresPublicidadDesarrolladoresTérminosPrivacidadPolítica y seguridadCómo funciona YouTubeProbar funciones nuevas
' +]; diff --git a/tests/cache/youtu.be.eihxasgrtca.php b/tests/cache/youtu.be.eihxasgrtca.php new file mode 100644 index 00000000..e5975799 --- /dev/null +++ b/tests/cache/youtu.be.eihxasgrtca.php @@ -0,0 +1,1190 @@ + [ + 'content-type' => [ + 'application/binary', + 'application/binary', + 'application/binary', + 'text/html; charset=utf-8' + ], + 'x-content-type-options' => [ + 'nosniff', + 'nosniff', + 'nosniff', + 'nosniff' + ], + 'cache-control' => [ + 'no-cache, no-store, max-age=0, must-revalidate', + 'no-cache, no-store, max-age=0, must-revalidate', + 'no-cache, no-store, max-age=0, must-revalidate', + 'no-cache, no-store, max-age=0, must-revalidate' + ], + 'pragma' => [ + 'no-cache', + 'no-cache', + 'no-cache', + 'no-cache' + ], + 'expires' => [ + 'Mon, 01 Jan 1990 00:00:00 GMT', + 'Mon, 01 Jan 1990 00:00:00 GMT', + 'Mon, 01 Jan 1990 00:00:00 GMT', + 'Mon, 01 Jan 1990 00:00:00 GMT' + ], + 'date' => [ + 'Sun, 04 Apr 2021 15:22:04 GMT', + 'Sun, 04 Apr 2021 15:22:04 GMT', + 'Sun, 04 Apr 2021 15:22:04 GMT', + 'Sun, 04 Apr 2021 15:22:06 GMT' + ], + 'location' => [ + 'https://youtu.be/eiHXASgRTcA', + 'https://www.youtube.com/watch?v=eiHXASgRTcA&feature=youtu.be', + 'https://consent.youtube.com/m?continue=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeiHXASgRTcA%26feature%3Dyoutu.be&gl=ES&m=0&pc=yt&uxe=23983172&hl=es&src=1' + ], + 'x-frame-options' => [ + 'SAMEORIGIN', + 'SAMEORIGIN', + 'SAMEORIGIN', + 'SAMEORIGIN' + ], + 'server' => [ + 'ESF', + 'ESF', + 'ESF', + 'ESF' + ], + 'content-length' => [ + '0', + '0', + '0' + ], + 'x-xss-protection' => [ + '0 HTTP/2 303', + '0', + '0', + '0' + ], + 'strict-transport-security' => [ + 'max-age=31536000', + 'max-age=31536000' + ], + 'p3p' => [ + 'CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=es for more info."', + 'CP="This is not a P3P policy! See g.co/p3phelp for more info."' + ], + 'set-cookie' => [ + 'YSC=NTEDmmAQwGA; Domain=.youtube.com; Path=/; Secure; HttpOnly; SameSite=none', + 'CONSENT=PENDING+372; expires=Fri, 01-Jan-2038 00:00:00 GMT; path=/; domain=.youtu.be', + 'CONSENT=PENDING+906; expires=Fri, 01-Jan-2038 00:00:00 GMT; path=/; domain=.youtube.com' + ], + 'alt-svc' => [ + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43" HTTP/2 302', + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43" HTTP/2 200', + 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"' + ], + 'vary' => [ + 'Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site' + ], + 'x-ua-compatible' => [ + 'IE=edge' + ], + 'origin-trial' => [ + 'AmWWqEiPtRKXiIreUsgUyNMptDcKdmLPlGI32DPZjDKK+yBAUi7+FT3r/9RpkTnzHyXYUWiPfirCGMg3Ogzc7gMAAAB3eyJvcmlnaW4iOiJodHRwczovL2dvb2dsZS5jb206NDQzIiwiZmVhdHVyZSI6IkNyb3NzT3JpZ2luT3BlbmVyUG9saWN5UmVwb3J0aW5nIiwiZXhwaXJ5IjoxNjE0MTI0Nzk5LCJpc1N1YmRvbWFpbiI6dHJ1ZX0=' + ], + 'cross-origin-opener-policy-report-only' => [ + 'same-origin; report-to="ConsentUi"' + ], + 'content-security-policy' => [ + 'script-src \'nonce-vXnNojUBz7Sepbt+v8Bipg\' \'unsafe-inline\';object-src \'none\';base-uri \'self\';report-uri /_/ConsentUi/cspreport;worker-src \'self\'', + 'script-src \'nonce-vXnNojUBz7Sepbt+v8Bipg\' \'self\' https://apis.google.com https://ssl.gstatic.com https://www.google.com https://www.gstatic.com https://www.google-analytics.com;report-uri /_/ConsentUi/cspreport' + ], + 'cross-origin-resource-policy' => [ + 'same-site' + ], + 'report-to' => [ + '{"group":"ConsentUi","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/ConsentUi/external"}]}' + ], + 'content-encoding' => [ + 'gzip' + ], + 'Content-Location' => [ + 'https://consent.youtube.com/m?continue=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeiHXASgRTcA%26feature%3Dyoutu.be&gl=ES&m=0&pc=yt&uxe=23983172&hl=es&src=1' + ], + 'X-Request-Time' => [ + '1.776 ms' + ] + ], + 'statusCode' => 200, + 'reasonPhrase' => 'OK', + 'body' => 'Antes de ir a YouTube
YouTube una empresa de Google

Antes de ir a YouTube

En Google utilizamos cookies y datos para:
  • Proporcionar y mantener servicios, como hacer un seguimiento de las interrupciones y prevenir el spam, el fraude y los abusos
  • Medir la interacción de la audiencia y estadísticas de los sitios web para entender cómo se utilizan nuestros servicios
Si aceptas, también usaremos las cookies y los datos para:
  • Mejorar la calidad de nuestros servicios y desarrollar otros nuevos
  • Mostrar anuncios y medir su eficacia
  • Mostrar contenido personalizado en función de tus ajustes
  • Mostrar anuncios genéricos o personalizados, en función de tus ajustes, en Google y en la Web
Con respecto al contenido y los anuncios no personalizados, lo que veas puede estar influido por factores como lo que estés viendo en ese momento y tu ubicación (el servicio de anuncios se basa en la ubicación general). El contenido y los anuncios personalizados se pueden basar, además de en esos criterios, en tu actividad, como las búsquedas que hagas en Google y los vídeos que veas en YouTube. Los anuncios y el contenido personalizados incluyen, entre otras cosas, resultados y recomendaciones más relevantes, una página de inicio de YouTube personalizada y anuncios adaptados a tus intereses.

Haz clic en Personalizar para ver las opciones disponibles, como los controles que permiten rechazar el uso de cookies para la personalización e información sobre los controles del navegador que permiten rechazar parte o la totalidad de las cookies para otros usos. También puedes visitar g.co/privacytools en cualquier momento.

' +]; diff --git a/tests/fixtures/4pda.to.2022-12-04-406834-sostoyalsya_reliz_clown_of_duty_parodii_na_call_of_duty.php b/tests/fixtures/4pda.to.2022-12-04-406834-sostoyalsya_reliz_clown_of_duty_parodii_na_call_of_duty.php new file mode 100644 index 00000000..f89ae429 --- /dev/null +++ b/tests/fixtures/4pda.to.2022-12-04-406834-sostoyalsya_reliz_clown_of_duty_parodii_na_call_of_duty.php @@ -0,0 +1,29 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Несмотря на успешный релиз Call of Duty: Modern Warfare II и Warzone 2.0, геймеры оказались не очень довольны техническим состоянием игр. Форум Reddit заполнен жалобами на баги и просьбами их исправить. Мольбы фанатов были услышаны — правда, другими разработчиками.', + 'favicon' => 'https://4pda.to/s/as6yYjz1ZD25PBECTAG7.png', + 'feeds' => [], + 'icon' => 'https://4pda.to/s/as6ywymaTWM6wnea1mxojxCz0Yet7IeumfOBnaxb.png', + 'image' => 'https://i.4pda.ws/s/as6yueQrUwnKt0LgJ5m26uBjbZsccTet21FqwJkADfGw.jpg?v=1669981373', + 'keywords' => [ + 'состоялся релиз clown of duty — пародии на call of duty' + ], + 'language' => 'ru-RU', + 'languages' => [], + 'license' => null, + 'providerName' => '4PDA - Новости мира мобильных устройств', + 'providerUrl' => 'https://4pda.to/', + 'publishedTime' => '2022-12-04 08:00:00', + 'redirect' => null, + 'title' => 'Состоялся релиз Clown of Duty — пародии на Call of Duty', + 'url' => 'https://4pda.to/2022/12/04/406834/sostoyalsya_reliz_clown_of_duty_parodii_na_call_of_duty/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/500px.com.photo-138251239-taganay-park-by-daniel-kordan.php b/tests/fixtures/500px.com.photo-138251239-taganay-park-by-daniel-kordan.php new file mode 100644 index 00000000..126ffc88 --- /dev/null +++ b/tests/fixtures/500px.com.photo-138251239-taganay-park-by-daniel-kordan.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://500px.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => '500px', + 'providerUrl' => 'https://500px.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => '500px', + 'url' => 'https://500px.com/photo/138251239/taganay-park-by-daniel-kordan', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/animoto.com.play-gjsj1gu0wdrfr4pgw12xzq.php b/tests/fixtures/animoto.com.play-gjsj1gu0wdrfr4pgw12xzq.php new file mode 100644 index 00000000..96c9fddf --- /dev/null +++ b/tests/fixtures/animoto.com.play-gjsj1gu0wdrfr4pgw12xzq.php @@ -0,0 +1,56 @@ + '@animoto', + 'authorUrl' => 'https://twitter.com/animoto', + 'cms' => null, + 'code' => null, + 'description' => 'Create, edit, and share videos with our free video maker. Combine your photos, video clips, and music to make quality videos in minutes. Get started free!', + 'favicon' => 'https://animoto.com/favicon-32x32.png?v=f7bad0df2a4af8688773dca5ee0b1ed6', + 'feeds' => [ + 'https://animoto.com/rss.xml' + ], + 'icon' => 'https://animoto.com/icons/icon-48x48.png?v=f7bad0df2a4af8688773dca5ee0b1ed6', + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Animoto', + 'providerUrl' => 'https://animoto.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Free Video Maker | Create & Edit Your Videos Easily', + 'url' => 'https://animoto.com/play/GjsJ1gu0WDRfr4pGw12xZQ', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'WebSite', + 'url' => 'https://animoto.com/', + 'name' => 'Animoto video maker - Stand out on social media. Easily.', + 'alternateName' => '' + ], + 'oEmbed' => [ + 'error' => 'URL not supported or not found', + 'url' => 'https://animoto.com/play/GjsJ1gu0WDRfr4pGw12xZQ' + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'WebSite', + 'url' => 'https://animoto.com/', + 'name' => 'Animoto video maker - Stand out on social media. Easily.', + 'alternateName' => '' + ], + [ + '@context' => 'http://schema.org/', + '@type' => 'VideoObject', + 'name' => 'Animoto: Free Online Video Maker', + 'contentUrl' => 'https://d2of6bhnpl91ni.cloudfront.net/cms/animoto-free-online-video-maker-e8d6870030.mp4', + 'description' => 'With Animoto, you\'ll have everything you need to create your own professional videos in minutes. No experience required. All it takes is an idea. ', + 'thumbnailUrl' => '//images.ctfassets.net/00i767ygo3tc/010bacg5wwIhMMx6xYS3qj/18e39c5d16f5614a3b477a284faea1a2/free-online-video-maker.webp', + 'transcript' => 'We all have a story to tell, and video is the best way to make yours stand out. With Animoto, you\'ll have everything you need to create your own professional videos in minutes. No experience required. All it takes is an idea. We\'ve made it easy to get started with customizable templates for everything from saying Happy Birthday to selling your product. From there, it\'s as simple as dragging and dropping your photos and video clips, choosing from our millions of Getty stock images or recording with our built-in screen and webcam recorder. Customize your videos with transitions, music, voiceovers, and more. Then bring your videos on brand with a single click. Make sure your story is heard with Animoto. Everything you need to create your own videos is right at your fingertips. Start creating for free.', + 'uploadDate' => '2020-09-15T21:58:55.636Z' + ] + ] +]; diff --git a/tests/fixtures/archive.org.details-dn2015-0220_vid.php b/tests/fixtures/archive.org.details-dn2015-0220_vid.php new file mode 100644 index 00000000..ea395b25 --- /dev/null +++ b/tests/fixtures/archive.org.details-dn2015-0220_vid.php @@ -0,0 +1,833 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 640, + 'height' => 480, + 'ratio' => 75.0 + ], + 'description' => 'Democracy Now! television program for Friday, February 20, 2015 Headlines for February 20, 2015 An Unsolved Case of Racial Terror: FBI Probes 1946...', + 'favicon' => 'https://archive.org/images/glogo.jpg', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://archive.org/download/dn2015-0220_vid/dn2015-0220_vid.thumbs/dn2015-0220_000090.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Internet Archive', + 'providerUrl' => 'https://archive.org/', + 'publishedTime' => '2015-02-20 00:00:00', + 'redirect' => null, + 'title' => 'Democracy Now! Friday, February 20, 2015', + 'url' => 'https://archive.org/details/dn2015-0220_vid', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'BreadcrumbList', + 'itemListElement' => [ + [ + '@type' => 'ListItem', + 'position' => 1, + 'item' => [ + '@id' => 'https://archive.org/details/movies', + 'name' => 'Videos', + 'image' => 'https://archive.org/services/img/movies' + ] + ] + ] + ], + 'oEmbed' => [], + 'api' => [ + 'server' => 'ia801600.us.archive.org', + 'dir' => '/34/items/dn2015-0220_vid', + 'metadata' => [ + 'identifier' => [ + 'dn2015-0220_vid' + ], + 'addeddate' => [ + '2015-02-20 00:00:00' + ], + 'mediatype' => [ + 'movies' + ], + 'title' => [ + 'Democracy Now! Friday, February 20, 2015' + ], + 'date' => [ + '2015-02-20' + ], + 'year' => [ + '2015' + ], + 'taper' => [ + 'DN Studios' + ], + 'source' => [ + 'Television broadcast' + ], + 'categories' => [ + 'Democracy Now' + ], + 'subject' => [ + 'Democracy Now' + ], + 'description' => [ + 'Democracy Now! television program for Friday, February 20, 2015 + +' + ], + 'language' => [ + 'en' + ], + 'publicdate' => [ + '2015-02-20 00:00:00' + ], + 'runtime' => [ + '59:02' + ], + 'color' => [ + 'color' + ], + 'sound' => [ + 'sound' + ], + 'closed_captioning' => [ + 'no' + ], + 'collection' => [ + 'democracy_now_vid', + 'newsandpublicaffairs' + ], + 'backup_location' => [ + 'ia905301_14' + ], + 'ia_orig__runtime' => [ + '59 minutes 2 seconds' + ] + ], + 'files' => [ + '/__ia_thumb.jpg' => [ + 'source' => 'original', + 'mtime' => '1539126011', + 'size' => '4660', + 'md5' => 'a7fdf9c9841c7d4438c0ecef58cbfb2e', + 'crc32' => '21b396c7', + 'sha1' => '69627aef4c817f4901f8437058ca67655c5acf8d', + 'format' => 'Item Tile', + 'rotation' => '0' + ], + '/dn2015-0220.gif' => [ + 'source' => 'derivative', + 'format' => 'Animated GIF', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424450976', + 'size' => '368631', + 'md5' => 'c45300918d2ca43827595efe8890de65', + 'crc32' => '69a0751e', + 'sha1' => '9b938921aaee6aba39d21aa70c7e86448a01efb2' + ], + '/dn2015-0220.mp4' => [ + 'source' => 'derivative', + 'format' => 'h.264', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424480294', + 'size' => '368442433', + 'md5' => '9883358631c40ef48f8538053add8474', + 'crc32' => '6beadd45', + 'sha1' => 'd5de45141922982e3ec5936e7fa14de3ef21f458', + 'length' => '3542.04', + 'height' => '480', + 'width' => '640' + ], + '/dn2015-0220.mpeg' => [ + 'source' => 'original', + 'mtime' => '1424441271', + 'size' => '3028289536', + 'md5' => '1c25765e8d3031adcc65ba07ee354a66', + 'crc32' => 'e2600afc', + 'sha1' => 'cc2a820aa7be18ce96586d467756af42860f39dc', + 'format' => 'MPEG2', + 'length' => '3542.02', + 'height' => '480', + 'width' => '640' + ], + '/dn2015-0220.mpeg.idx' => [ + 'source' => 'derivative', + 'format' => 'Video Index', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451020', + 'size' => '2934751', + 'md5' => '6f021022e197873cecb0ff06b2e71bfe', + 'crc32' => 'c8129a20', + 'sha1' => '343fd4ab097a54a3fc30a4a03fb98ba53a57ea4d' + ], + '/dn2015-0220.ogv' => [ + 'source' => 'derivative', + 'format' => 'Ogg Video', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424488111', + 'size' => '267227655', + 'md5' => '7e19542e5587e380f7a00d71d742ee4b', + 'crc32' => '106921ba', + 'sha1' => '09159069195a61815f59fb276dd81e5b32d3e925', + 'length' => '3542.02', + 'height' => '300', + 'width' => '400' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000001.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451046', + 'size' => '6144', + 'md5' => '66f6e3657aceecce5082fc1b8e1c36b7', + 'crc32' => 'c2935285', + 'sha1' => '63287b509a45f20f31856acbf773d30f72f882b1' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000090.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451072', + 'size' => '4434', + 'md5' => '2989bf9f4634fd132f6cd21c738e130c', + 'crc32' => 'f8f9860c', + 'sha1' => '6bbeed2f963fcbf8f1361d10ec2e1c8472b93f0a' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000150.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451097', + 'size' => '6543', + 'md5' => 'ba120fba0fed088eb4ca1cc1299dc1b1', + 'crc32' => 'cc52d87d', + 'sha1' => '595ab0dc0d66e1f232c813ce0962d1ea1b6a0efb' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000210.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451122', + 'size' => '6142', + 'md5' => 'fd4d00547ccbea14c6f5b4e1e0b0b1d0', + 'crc32' => '46b6e4e5', + 'sha1' => '3b0e1907338454d550078e4a0b265fbf90165c1c' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000270.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451145', + 'size' => '8106', + 'md5' => '94d26c882a7fbed256f7668a228d50b1', + 'crc32' => 'ce04759e', + 'sha1' => '3872cf21383a47e9f90f99b4e05e5c187cd9ddf8' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000330.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451182', + 'size' => '6041', + 'md5' => 'ab9978595612c454bb6fb50c99d7b384', + 'crc32' => 'f51f2c25', + 'sha1' => '0ed45452a4dcb750277d669aabfef2711d1b74ae' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000390.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451205', + 'size' => '7273', + 'md5' => 'bd0d136f2edbac5298d21bde5ed9415b', + 'crc32' => 'e2139fe3', + 'sha1' => 'd0c3d604c336d89a325f64aa9f9b9303e656ba89' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000450.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451229', + 'size' => '5864', + 'md5' => '2da03fea59bc7fabf9e90f33c82909e0', + 'crc32' => '1fab040a', + 'sha1' => '3af5ec7c26428eb647c71052dc79072af1bd2ebb' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000510.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451253', + 'size' => '5872', + 'md5' => 'b9f043538546af668aec570ecc084a95', + 'crc32' => '8353be38', + 'sha1' => '159140d40b69abcdb89024482ba2b238d7f9b171' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000570.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451272', + 'size' => '5433', + 'md5' => '33d7f013bdd73ce47ee6ad47b953fcf7', + 'crc32' => '7884738b', + 'sha1' => 'b3ff9c16a11d3eeaa7096fd41e281175b0b1dda4' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000630.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451290', + 'size' => '5230', + 'md5' => 'de790b055419bd283dcaddd7300b6cc3', + 'crc32' => 'a792d351', + 'sha1' => 'efa379cf9ef3323ead1c16d4c4c116993418c34b' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000690.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451308', + 'size' => '5795', + 'md5' => 'c626e4a15c4ffa14bff283ace91b634f', + 'crc32' => '1e36c8e9', + 'sha1' => '36179a1a90c3d607368649a8279636ff60def686' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000750.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451332', + 'size' => '6502', + 'md5' => 'abce241ddd7f761b626d8df2f04f4196', + 'crc32' => '04ee4fee', + 'sha1' => '3c81ddba2166e6cfd4c5befd8b03a39a38f4421d' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000810.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451356', + 'size' => '3823', + 'md5' => 'e0adbe7a20cbb5f4a2be949c511d192d', + 'crc32' => 'f40aa1f3', + 'sha1' => 'f091115a7c3f0bb7c8056f0ac05e47084b3ecd94' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000870.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451382', + 'size' => '4863', + 'md5' => '0dd6763254ada56546cab158926da844', + 'crc32' => '040ea0cd', + 'sha1' => 'a663772ad6f4c67b7f17cf57706a637173849a1f' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000930.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451405', + 'size' => '5944', + 'md5' => '5b98fca01603821b3ce7a735a4443ba7', + 'crc32' => 'c4b57192', + 'sha1' => '5ed33e1bc7d5cb3666fe056b963fb3640db8cb74' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_000990.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451428', + 'size' => '5692', + 'md5' => 'd9a94f4303bf6a7b20eacd695ae71b20', + 'crc32' => 'c074c598', + 'sha1' => 'cf1537e36f56fdca8a658872876ae91b9938cc19' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001050.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451451', + 'size' => '5633', + 'md5' => '2ee5fa0c457ed4ec5cc74f40359d4645', + 'crc32' => '4a94e488', + 'sha1' => '4acc460f6c3d5123204b0dddd1f6992717e3ea80' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001110.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451466', + 'size' => '8020', + 'md5' => '11070bb90df260ec13c149cac2b6d35d', + 'crc32' => '46304160', + 'sha1' => 'aafe4d8eaca8c87ef937899388d61e5eb0671393' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001170.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451491', + 'size' => '4849', + 'md5' => 'e6e9da95ed8faff66e4516d604609f00', + 'crc32' => '1b4cd468', + 'sha1' => '9836ab4e8809bc857798175cd28d3ddbfc78cf9b' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001230.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451512', + 'size' => '8041', + 'md5' => 'd9bb2bb534355c2d3e37321fc33aed0a', + 'crc32' => 'ee651b82', + 'sha1' => '17a6284c78475d2ca9d7e5d9e2593ee97a3b186f' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001290.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451535', + 'size' => '7143', + 'md5' => 'df5926b2679ce504e15e2d2cf3edc8b8', + 'crc32' => 'd0f450ab', + 'sha1' => 'aa76a10bde421a447674e737076cb1404a4aa6f3' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001350.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451564', + 'size' => '7853', + 'md5' => '53f1c301cee93ba7f4d571658e67fb66', + 'crc32' => '37998263', + 'sha1' => '425cf1b918a077107b13c020d16082ac269bbb29' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001410.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451588', + 'size' => '4584', + 'md5' => '793069d70a58abf7d45d8b70fb6ee25b', + 'crc32' => 'ed5b104d', + 'sha1' => '84dfecff477557831039188914bcf548665b24e4' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001470.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451611', + 'size' => '8896', + 'md5' => '4c919cb8b5c9370c05cf48a5217fcbe9', + 'crc32' => 'b3f97a9c', + 'sha1' => 'd8da38fe6fdbd4e9c21ed314c69dd0f422d135ad' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001530.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451637', + 'size' => '4964', + 'md5' => 'df17c9a76d68e1074ec5b46d87211c70', + 'crc32' => '6ef97a80', + 'sha1' => 'ded26b656d9031e530aa4d96e0f4138649c31520' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001590.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451655', + 'size' => '5314', + 'md5' => 'bc66effb8aa421aeda194e5f6908f9d9', + 'crc32' => '41d7620c', + 'sha1' => '371a67db8d9197b852f43d383415a28bdf462530' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001650.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451681', + 'size' => '3528', + 'md5' => '6fb7687b42c1ec31af34810ea9c3828c', + 'crc32' => '7c441ec7', + 'sha1' => '87d2710cf9d391e4471b3d650c4f690bd3bd1ea9' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001710.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451705', + 'size' => '4889', + 'md5' => '16ab6e2714dd5d69757baff23f1bb687', + 'crc32' => '2937ad0e', + 'sha1' => '454cf1a8838985bb1e6edb4c876dd170609b8eea' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001770.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451726', + 'size' => '5956', + 'md5' => '8103bdb32a9f8e1f476b202df2d07381', + 'crc32' => '5ebf18f0', + 'sha1' => 'a03e7a70f2410e783616f0ffafe3b2cf4ae59eb3' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001830.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451749', + 'size' => '4030', + 'md5' => 'ecefe0c4cd7fb85d9eeb8f4394a44925', + 'crc32' => '7bc14197', + 'sha1' => 'ad2038e59cd3ec46757184a4ad69d964a48bb146' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001890.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451772', + 'size' => '3927', + 'md5' => '75f1b80c95a3af685aa7804bea77b956', + 'crc32' => '8b3a7e6c', + 'sha1' => '890a75d1a07f64b9f49a1da6650d6cfb9ce01c51' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_001950.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451797', + 'size' => '4160', + 'md5' => '279de49dd35fe2bd1d4112eceb638abd', + 'crc32' => '38c76305', + 'sha1' => 'ca38dbd7b8e790f87f70f2a986039057f753150f' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002010.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451825', + 'size' => '4756', + 'md5' => '9452951d8ce3d4a6f6a3ac6f2780ec01', + 'crc32' => 'f7e0766f', + 'sha1' => '809949c25e2c657349bba307ae408859eb213517' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002070.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451850', + 'size' => '7077', + 'md5' => '07a51b68c6be2319b8f4d91ece4bce3f', + 'crc32' => '467fd0d9', + 'sha1' => 'af27b1e6832d55dd6f3d8ff79b2a69707266bfd2' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002130.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451874', + 'size' => '7078', + 'md5' => 'a91b91effe56969cca263445a479eb0f', + 'crc32' => '8c8215d7', + 'sha1' => '89359a449f5930cab6056cbed2ac0f00bc86a210' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002190.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451897', + 'size' => '4934', + 'md5' => '855468ec5b258af349a39ed8ba6de326', + 'crc32' => '6546e4f6', + 'sha1' => 'bc9501a0d03a1680d49701c93ef3460b17c2c95f' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002250.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451937', + 'size' => '8913', + 'md5' => 'ac1a5af7261163e45ebffc5261ba80d3', + 'crc32' => 'b74c7561', + 'sha1' => '019bba015cda5282b8fa2726a3e4e969ad8a12ed' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002310.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424451971', + 'size' => '7797', + 'md5' => '081c5cd887176b79caff5ea304442714', + 'crc32' => '0abecb1d', + 'sha1' => '4c1a78c19bc152cd94df8b9c81285e950ecd495c' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002370.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452001', + 'size' => '7884', + 'md5' => '1281d43fb6f73e9f97c7085d28ea5c02', + 'crc32' => '736fb6e3', + 'sha1' => '7eaf252d5443104eedd9acb5764966e7b5cb0105' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002430.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452031', + 'size' => '8082', + 'md5' => '7029a522bd4f02f825d86987be2b2e29', + 'crc32' => 'a9fe1dce', + 'sha1' => '163c4ce309979f7d0b9c33daf17559892fb50c34' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002490.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452064', + 'size' => '7797', + 'md5' => '0faf61bf22d8fc18ed4ba47419e750d2', + 'crc32' => 'e8d44d2a', + 'sha1' => '66d236228b88ee7ce600cf70efcae797dfc876a6' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002550.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452092', + 'size' => '7530', + 'md5' => '3682bb2888213fe6ee522406fd46124a', + 'crc32' => 'f5512a32', + 'sha1' => 'd5c45b80cf241854c1fb7caa26b894b4ccffd333' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002610.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452119', + 'size' => '8211', + 'md5' => 'a84ba6f813faef974a98167f4161be64', + 'crc32' => '1f219f6b', + 'sha1' => '3b7b681fd2a4824c27f0bd755c940ea33b7f46a8' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002670.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452152', + 'size' => '8834', + 'md5' => 'dd31b5ff578e9fa12e0ad7129a500651', + 'crc32' => '576045ca', + 'sha1' => '9f7ec2f962bba93b37e9b4d3ef21fab33b6328fa' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002730.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452183', + 'size' => '8114', + 'md5' => 'dbcd8987c9315ed2a4563cfda70c2c8b', + 'crc32' => '7a0b8c83', + 'sha1' => '3ad13bebd6372d4eabae6e5b036e3755eec11039' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002790.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452210', + 'size' => '6765', + 'md5' => 'bb9db289a45369a98762ebfa3aecf351', + 'crc32' => '9c96ee7d', + 'sha1' => 'f7370b794ee34332bf504858a31e32e568d06ad8' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002850.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452230', + 'size' => '5396', + 'md5' => 'b4ecbee825cb067a75854d62898c8483', + 'crc32' => 'f909320d', + 'sha1' => 'ed7be9066f31c831f2548d13d043dec756a21b60' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002910.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452246', + 'size' => '5607', + 'md5' => 'b035f5f83d07f8c4ed1aff3877331f4b', + 'crc32' => '68fd4a93', + 'sha1' => '1e8dcb2bf8be564ff28d8f15d402e6b9f569b173' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_002970.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452272', + 'size' => '4465', + 'md5' => '7fa974d10b63629547abac4b20795bbf', + 'crc32' => '5373311e', + 'sha1' => 'c6ab42cef07a06af337b6c5926c7e2bd44bab763' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003030.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452292', + 'size' => '7918', + 'md5' => '960cad667a523997bf3792ed786b7187', + 'crc32' => '969082bf', + 'sha1' => '24dd55448f22d3979fe59ea201d4f1ffeeac4ab0' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003090.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452331', + 'size' => '5640', + 'md5' => '5c1113a6b297edfe8f6b2c74a16948e8', + 'crc32' => 'a78e20ba', + 'sha1' => '4f31ecb38e568a6accc625e822158c1305e416b3' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003150.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452363', + 'size' => '7174', + 'md5' => 'aae62b432f3163d05d6329bcb167183b', + 'crc32' => '36338f84', + 'sha1' => 'a3a56abfb1b8d54f76675524b904123cc5c12949' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003210.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452400', + 'size' => '7125', + 'md5' => '2976cf92a8ccf219d29a9e8034a21495', + 'crc32' => 'd9e2cb37', + 'sha1' => '78f1cdf5ebde818225daa20db0b3cc4c2e1749f2' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003270.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452424', + 'size' => '7020', + 'md5' => '91ae9e89012ce1679243abff46edaadb', + 'crc32' => '57d2e2ec', + 'sha1' => '0e2232c336098ba9ab9501f1c432f25a49168ba7' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003330.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452443', + 'size' => '6036', + 'md5' => '13789bc18f362629a1a52a608f0a61c8', + 'crc32' => 'edff0756', + 'sha1' => '75b807963832d60f4e38218ad114e5b16d0ea838' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003390.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452467', + 'size' => '5054', + 'md5' => '2cf10cbe6830d1ee3c83bb08eb471a9c', + 'crc32' => '15cb42c1', + 'sha1' => 'a60cb92278404881c66c6a01998fae045028e1a5' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003450.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452489', + 'size' => '7053', + 'md5' => '973fc1a89ce0ef15005a2b287a6d4e17', + 'crc32' => 'b43324a8', + 'sha1' => '3c5cb87aeea11bacfb88b510bee473b7561ecbce' + ], + '/dn2015-0220_vid.thumbs/dn2015-0220_003510.jpg' => [ + 'source' => 'derivative', + 'format' => 'Thumbnail', + 'original' => 'dn2015-0220.mpeg', + 'mtime' => '1424452517', + 'size' => '6046', + 'md5' => '6248f0d6af501c1ec9a127bb0802a08e', + 'crc32' => 'a621da55', + 'sha1' => 'baf770c026701bbb3e288b6eadba29703aae87e0' + ], + '/dn2015-0220_vid_archive.torrent' => [ + 'source' => 'original', + 'btih' => 'd3f9f4af56caa39e94b7f85ce7d7b9e722163341', + 'mtime' => '1542757137', + 'size' => '37836', + 'md5' => 'c861226dbe6e4b211c5290e5b4a1ba8d', + 'crc32' => 'd9aca1b6', + 'sha1' => '12875539f9104546176f32edfac2140004703c47', + 'format' => 'Archive BitTorrent' + ], + '/dn2015-0220_vid_files.xml' => [ + 'source' => 'original', + 'format' => 'Metadata', + 'md5' => 'c8085d21bd5d528af0697f7d1cfff599', + 'summation' => 'md5' + ], + '/dn2015-0220_vid_meta.xml' => [ + 'source' => 'original', + 'mtime' => '1675274129', + 'size' => '1973', + 'format' => 'Metadata', + 'md5' => '6a144c80a58ab5f08c0ecffdb580954a', + 'crc32' => 'a0ce73ae', + 'sha1' => '478a1338b524d61776aebe9c0e8aca57a38a5dfc' + ] + ], + 'misc' => [ + 'image' => 'https://ia801600.us.archive.org/34/items/dn2015-0220_vid/dn2015-0220.gif', + 'collection-title' => 'Democracy Now!' + ], + 'item' => [ + 'downloads' => 156, + 'month' => 0, + 'item_size' => 3667677269, + 'files_count' => 68, + 'item_count' => null, + 'collection_files_count' => null, + 'collection_size' => null + ] + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'BreadcrumbList', + 'itemListElement' => [ + [ + '@type' => 'ListItem', + 'position' => 1, + 'item' => [ + '@id' => 'https://archive.org/details/movies', + 'name' => 'Videos', + 'image' => 'https://archive.org/services/img/movies' + ] + ] + ] + ] + ] +]; diff --git a/tests/fixtures/archive.org.details-librivoxaudio.php b/tests/fixtures/archive.org.details-librivoxaudio.php new file mode 100644 index 00000000..0ee5c49b --- /dev/null +++ b/tests/fixtures/archive.org.details-librivoxaudio.php @@ -0,0 +1,35 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 640, + 'height' => 480, + 'ratio' => 75.0 + ], + 'description' => 'LibriVox - founded in 2005 - is a community of volunteers from all over the world who record public domain texts: poetry, short stories, whole books, even dramatic works, in many different languages. All LibriVox recordings are in the public domain in the USA and available as free downloads on...', + 'favicon' => 'https://archive.org/images/glogo.jpg', + 'feeds' => [ + 'http://archive.org/services/collection-rss.php?collection=librivoxaudio' + ], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Internet Archive', + 'providerUrl' => 'https://archive.org/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'The LibriVox Free Audiobook Collection : Free Audio : Free Download, Borrow and Streaming : Internet Archive', + 'url' => 'https://archive.org/details/librivoxaudio', + 'linkedData' => [], + 'oEmbed' => [], + 'api' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/buff.ly.2usohds.php b/tests/fixtures/buff.ly.2usohds.php new file mode 100644 index 00000000..3c7b4460 --- /dev/null +++ b/tests/fixtures/buff.ly.2usohds.php @@ -0,0 +1,102 @@ + '@graffica_info', + 'authorUrl' => 'https://twitter.com/graffica_info', + 'cms' => null, + 'code' => null, + 'description' => 'El lenguaje, sea cual sea el idioma, siempre esconde entre los orígenes de sus palabras muchas curiosidades. Este es el caso del origen del ampersand.', + 'favicon' => 'https://graffica.info/favicon.ico', + 'feeds' => [ + 'https://graffica.info/wp-json/wp/v2/posts/290566', + 'https://graffica.info/feed/' + ], + 'icon' => null, + 'image' => 'https://graffica.info/wp-content/uploads/2020/02/el-origen-de-la-Ampersand-destacado.jpg', + 'keywords' => [], + 'language' => 'es', + 'languages' => [], + 'license' => null, + 'providerName' => 'Gràffica', + 'providerUrl' => 'https://graffica.info/', + 'publishedTime' => '2020-02-20 09:30:00', + 'redirect' => null, + 'title' => 'El origen del ampersand que desconocen muchos diseñadores', + 'url' => 'https://graffica.info/sabes-cual-es-el-origen-del-ampersand/', + 'linkedData' => [ + 'url' => 'https://graffica.info/', + 'name' => 'Gràffica', + '@id' => '#organization', + '@context' => 'http://schema.org/', + '@type' => 'Organization' + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + 'url' => 'https://graffica.info/', + 'name' => 'Gràffica', + '@id' => '#organization', + '@context' => 'http://schema.org/', + '@type' => 'Organization' + ], + [ + 'isPartOf' => [ + '@id' => '#website', + '@context' => 'http://schema.org/', + '@type' => 'WebSite' + ], + 'name' => '¿Sabes cuál es el origen del ampersand?', + '@id' => '#webpage', + '@context' => 'http://schema.org/', + '@type' => 'WebPage' + ], + [ + 'potentialAction' => [ + 'target' => 'https://graffica.info/?s={search_term_string}', + 'query-input' => 'required name=search_term_string', + '@context' => 'http://schema.org/', + '@type' => 'SearchAction' + ], + 'url' => 'https://graffica.info/', + 'name' => 'Gràffica', + 'description' => 'Revista de noticias del mundo del diseño, en especial del diseño gráfico, la creatividad y la cultura visual. Tipografía, ilustración, branding y mucho más.', + 'publisher' => [ + '@id' => '#organization', + '@context' => 'http://schema.org/', + '@type' => 'Organization' + ], + '@id' => '#website', + '@context' => 'http://schema.org/', + '@type' => 'WebSite' + ], + [ + 'dateModified' => '2020-11-16T11:54:05+01:00', + 'author' => [ + 'url' => 'https://graffica.info/author/anagamontessgmail-com/', + 'name' => 'Ana García Montes', + '@context' => 'http://schema.org/', + '@type' => 'Person' + ], + 'mainEntityOfPage' => [ + '@id' => '#webpage', + '@context' => 'http://schema.org/', + '@type' => 'WebPage' + ], + 'description' => 'El lenguaje, sea cual sea el idioma, siempre esconde entre los orígenes de sus palabras muchas curiosidades que resultan realmente fascinantes y que nos ayudan a entender el porqué de muchas formaciones lingüísticas. Este es el caso del origen del ampersand, el signo & —que en español su nombre es et y en inglés ampersand— […]', + 'datePublished' => '2020-02-20T10:30:00+01:00', + 'headline' => '¿Sabes cuál es el origen del ampersand?', + 'publisher' => [ + '@id' => '#organization', + '@context' => 'http://schema.org/', + '@type' => 'Organization' + ], + 'image' => [ + 'https://graffica.info/wp-content/uploads/2020/02/el-origen-de-la-Ampersand-destacado.jpg', + 'https://please-enter-a-fallback-url.here/' + ], + '@context' => 'http://schema.org/', + '@type' => 'Article' + ] + ] +]; diff --git a/tests/fixtures/calendar.google.com.calendar-embed.95ba7bc228ac2f81591bfa9cd9d2da50.php b/tests/fixtures/calendar.google.com.calendar-embed.95ba7bc228ac2f81591bfa9cd9d2da50.php new file mode 100644 index 00000000..5bb0a415 --- /dev/null +++ b/tests/fixtures/calendar.google.com.calendar-embed.95ba7bc228ac2f81591bfa9cd9d2da50.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://calendar.google.com/googlecalendar/images/favicons_2020q4/calendar_31.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Google', + 'providerUrl' => 'https://calendar.google.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Festivos en España', + 'url' => 'https://calendar.google.com/calendar/embed?src=spain__es%40holiday.calendar.google.com&ctz=Europe/Madrid', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/cdn2.thecatapi.com.images-cjd.jpg.php b/tests/fixtures/cdn2.thecatapi.com.images-cjd.jpg.php new file mode 100644 index 00000000..97229788 --- /dev/null +++ b/tests/fixtures/cdn2.thecatapi.com.images-cjd.jpg.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'https://cdn2.thecatapi.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://cdn2.thecatapi.com/images/cjd.jpg', + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Thecatapi', + 'providerUrl' => 'https://cdn2.thecatapi.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => null, + 'url' => 'https://cdn2.thecatapi.com/images/cjd.jpg', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/chirb.it.7a9l9b.php b/tests/fixtures/chirb.it.7a9l9b.php new file mode 100644 index 00000000..4ec76928 --- /dev/null +++ b/tests/fixtures/chirb.it.7a9l9b.php @@ -0,0 +1,50 @@ + 'nvanderklippe', + 'authorUrl' => 'https://www.chirbit.com/nvanderklippe', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 380, + 'height' => 120, + 'ratio' => 31.579 + ], + 'description' => 'Audio: - social audio', + 'favicon' => 'https://chirb.it/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://chirb.it/chirbit_oembedpic.jpg', + 'keywords' => [ + 'chirbit', + 'social audio', + '#conference' + ], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'chirbit', + 'providerUrl' => 'https://www.chirbit.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Encana conference call', + 'url' => 'https://chirb.it/7A9L9B', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'rich', + 'provider_name' => 'chirbit', + 'provider_url' => 'https://www.chirbit.com/', + 'thumbnail_url' => 'https://chirb.it/chirbit_oembedpic.jpg', + 'thumbnail_width' => 120, + 'thumbnail_height' => 120, + 'width' => '380', + 'height' => '120', + 'title' => 'Encana conference call', + 'author_name' => 'nvanderklippe', + 'author_url' => 'https://www.chirbit.com/nvanderklippe', + 'html' => '' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/codepen.io.zhouzi-pen-jorazp.php b/tests/fixtures/codepen.io.zhouzi-pen-jorazp.php new file mode 100644 index 00000000..24e7196f --- /dev/null +++ b/tests/fixtures/codepen.io.zhouzi-pen-jorazp.php @@ -0,0 +1,47 @@ + 'Gabin Aureche', + 'authorUrl' => 'https://codepen.io/Zhouzi', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 800, + 'height' => 300, + 'ratio' => 37.5 + ], + 'description' => null, + 'favicon' => 'https://codepen.io/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://shots.codepen.io/username/pen/JoRazP-512.jpg?version=1467971314', + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => null, + 'providerName' => 'CodePen', + 'providerUrl' => 'https://codepen.io/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'TheaterJS', + 'url' => 'https://codepen.io/Zhouzi/pen/JoRazP', + 'linkedData' => [], + 'oEmbed' => [ + 'success' => true, + 'type' => 'rich', + 'version' => '1.0', + 'provider_name' => 'CodePen', + 'provider_url' => 'https://codepen.io/', + 'title' => 'TheaterJS', + 'author_name' => 'Gabin Aureche', + 'author_url' => 'https://codepen.io/Zhouzi', + 'height' => '300', + 'width' => '800', + 'thumbnail_width' => '384', + 'thumbnail_height' => '225', + 'thumbnail_url' => 'https://shots.codepen.io/username/pen/JoRazP-512.jpg?version=1467971314', + 'html' => '' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/commondatastorage.googleapis.com.gtv-videos-bucket-sample-bigbuckbunny.mp4.php b/tests/fixtures/commondatastorage.googleapis.com.gtv-videos-bucket-sample-bigbuckbunny.mp4.php new file mode 100644 index 00000000..5ff0d4b6 --- /dev/null +++ b/tests/fixtures/commondatastorage.googleapis.com.gtv-videos-bucket-sample-bigbuckbunny.mp4.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'http://commondatastorage.googleapis.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Commondatastorage', + 'providerUrl' => 'http://commondatastorage.googleapis.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => null, + 'url' => 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/consent.google.es.ml.0bcc06470676961770c2d2357693454b.php b/tests/fixtures/consent.google.es.ml.0bcc06470676961770c2d2357693454b.php new file mode 100644 index 00000000..4e658006 --- /dev/null +++ b/tests/fixtures/consent.google.es.ml.0bcc06470676961770c2d2357693454b.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://consent.google.es/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Google', + 'providerUrl' => 'https://consent.google.es/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Error 404 (No se ha encontrado.)!!1', + 'url' => 'https://consent.google.es//'https:/consent.google.es/ml?continue=https://www.google.es/maps/place/Tordoia,%2BA%2BCoru%25C3%25B1a/@43.0871207,-8.5710004,12z/data%3D!3m1!4b1!4m2!3m1!1s0xd2ef4006f1ef489:0x404f58273ca55a0&gl=ES&hl=es&pc=m&src=1&rffu=true\'', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/consent.google.es.ml.2d8b4c7aacb24b7a0a3dabeac8b062b4.php b/tests/fixtures/consent.google.es.ml.2d8b4c7aacb24b7a0a3dabeac8b062b4.php new file mode 100644 index 00000000..94850b31 --- /dev/null +++ b/tests/fixtures/consent.google.es.ml.2d8b4c7aacb24b7a0a3dabeac8b062b4.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://www.google.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'es', + 'languages' => [], + 'license' => null, + 'providerName' => 'Google', + 'providerUrl' => 'https://consent.google.es/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Antes de ir a Google Maps', + 'url' => 'https://consent.google.es/ml?continue=https://www.google.es/maps/place/Tordoia,%2BA%2BCoru%25C3%25B1a/@43.0871207,-8.5710004,12z/data%3D!3m1!4b1!4m2!3m1!1s0xd2ef4006f1ef489:0x404f58273ca55a0&gl=ES&hl=es&cm=2&pc=m&uxe=eomtm&src=1&rffu=true', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.php b/tests/fixtures/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.php new file mode 100644 index 00000000..3cb48429 --- /dev/null +++ b/tests/fixtures/consent.youtube.com.ml.96e9b7b22bbf367fbeaa2ae77c21e90d.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://consent.youtube.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Youtube', + 'providerUrl' => 'https://consent.youtube.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Error 404 (No se ha encontrado.)!!1', + 'url' => 'https://consent.youtube.com//'https:/consent.youtube.com/ml?continue=https://www.youtube.com/channel/UCuZeHD5SGecQomz2pVDHGzg&gl=ES&hl=es&pc=yt&uxe=23983172&src=1&rffu=true\'', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/drive.google.com.file-d-0b2rwn8wabvswbmfjdudnv2vsttg-view.php b/tests/fixtures/drive.google.com.file-d-0b2rwn8wabvswbmfjdudnv2vsttg-view.php new file mode 100644 index 00000000..db8c0b4a --- /dev/null +++ b/tests/fixtures/drive.google.com.file-d-0b2rwn8wabvswbmfjdudnv2vsttg-view.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://drive.google.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Google', + 'providerUrl' => 'https://drive.google.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => null, + 'url' => 'https://drive.google.com/file/d/0B2rwN8wAbVSWbmFJdUdnV2VSTTg/view', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/en.wikipedia.org.wiki-albert_einstein.php b/tests/fixtures/en.wikipedia.org.wiki-albert_einstein.php new file mode 100644 index 00000000..cdd7cb1a --- /dev/null +++ b/tests/fixtures/en.wikipedia.org.wiki-albert_einstein.php @@ -0,0 +1,89 @@ + null, + 'authorUrl' => null, + 'cms' => 'mediawiki', + 'code' => null, + 'description' => 'Albert Einstein ( EYEN-styne; German: [ˈalbɛɐt ˈʔaɪnʃtaɪn] ; 14 March 1879 – 18 April 1955) was a German-born theoretical physicist who is widely held to be one of the greatest and most influential scientists of all time. Best known for developing the theory of relativity, Einstein also made important contributions to quantum mechanics, and was thus a central figure in the revolutionary reshaping of the scientific understanding of nature that modern physics accomplished in the first decades of the twentieth century. His mass–energy equivalence formula E = mc2, which arises from relativity theory, has been called "the world\'s most famous equation". He received the 1921 Nobel Prize in Physics "for his services to theoretical physics, and especially for his discovery of the law...', + 'favicon' => 'https://en.wikipedia.org/static/favicon/wikipedia.ico', + 'feeds' => [ + 'https://en.wikipedia.org/w/index.php?title=Special:RecentChanges&feed=atom' + ], + 'icon' => 'https://en.wikipedia.org/static/apple-touch/wikipedia.png', + 'image' => 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Einstein_1921_by_F_Schmutzer_-_restoration.jpg/1200px-Einstein_1921_by_F_Schmutzer_-_restoration.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Wikipedia', + 'providerUrl' => 'https://en.wikipedia.org/', + 'publishedTime' => '2001-11-05 18:26:16', + 'redirect' => null, + 'title' => 'Albert Einstein', + 'url' => 'https://en.wikipedia.org/wiki/Albert_Einstein', + 'linkedData' => [ + '@context' => 'https://schema.org/', + '@type' => 'Article', + 'name' => 'Albert Einstein', + 'url' => 'https://en.wikipedia.org/wiki/Albert_Einstein', + 'sameAs' => 'http://www.wikidata.org/entity/Q937', + 'mainEntity' => 'http://www.wikidata.org/entity/Q937', + 'author' => [ + '@type' => 'Organization', + 'name' => 'Contributors to Wikimedia projects' + ], + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'Wikimedia Foundation, Inc.', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.wikimedia.org/static/images/wmf-hor-googpub.png' + ] + ], + 'datePublished' => '2001-11-05T18:26:16Z', + 'dateModified' => '2024-06-04T23:38:54Z', + 'image' => 'https://upload.wikimedia.org/wikipedia/commons/3/3e/Einstein_1921_by_F_Schmutzer_-_restoration.jpg', + 'headline' => 'German-born theoretical physicist; developer of the theory of relativity (1879–1955)' + ], + 'oEmbed' => [], + 'api' => [ + 'pageid' => 736, + 'ns' => 0, + 'title' => 'Albert Einstein', + 'extract' => '

+ + + +

+ +

Albert Einstein ( EYEN-styne; German: [ˈalbɛɐt ˈʔaɪnʃtaɪn] ; 14 March 1879 – 18 April 1955) was a German-born theoretical physicist who is widely held to be one of the greatest and most influential scientists of all time. Best known for developing the theory of relativity, Einstein also made important contributions to quantum mechanics, and was thus a central figure in the revolutionary reshaping of the scientific understanding of nature that modern physics accomplished in the first decades of the twentieth century. His mass–energy equivalence formula E = mc2, which arises from relativity theory, has been called "the world\'s most famous equation". He received the 1921 Nobel Prize in Physics "for his services to theoretical physics, and especially for his discovery of the law

...' + ], + 'allLinkedData' => [ + [ + '@context' => 'https://schema.org/', + '@type' => 'Article', + 'name' => 'Albert Einstein', + 'url' => 'https://en.wikipedia.org/wiki/Albert_Einstein', + 'sameAs' => 'http://www.wikidata.org/entity/Q937', + 'mainEntity' => 'http://www.wikidata.org/entity/Q937', + 'author' => [ + '@type' => 'Organization', + 'name' => 'Contributors to Wikimedia projects' + ], + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'Wikimedia Foundation, Inc.', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.wikimedia.org/static/images/wmf-hor-googpub.png' + ] + ], + 'datePublished' => '2001-11-05T18:26:16Z', + 'dateModified' => '2024-06-04T23:38:54Z', + 'image' => 'https://upload.wikimedia.org/wikipedia/commons/3/3e/Einstein_1921_by_F_Schmutzer_-_restoration.jpg', + 'headline' => 'German-born theoretical physicist; developer of the theory of relativity (1879–1955)' + ] + ] +]; diff --git a/tests/fixtures/gist.github.com.oscarotero-7749998.php b/tests/fixtures/gist.github.com.oscarotero-7749998.php new file mode 100644 index 00000000..4d74b347 --- /dev/null +++ b/tests/fixtures/gist.github.com.oscarotero-7749998.php @@ -0,0 +1,340 @@ + 'oscarotero', + 'authorUrl' => 'https://github.com/oscarotero', + 'cms' => null, + 'code' => [ + 'html' => '
# Undo latest commit
git reset --soft HEAD^
# Undo the changes of a commit (creating a new commit)
git revert <commit>
# Undo latest merge (before push)
git reset --merge ORIG_HEAD
# Merge a branch using the version of the current branch in case of conflicts
git merge <branch> -s ours
# Discard changes for a particular file after commit
git reset HEAD <file>
# Unstage the current staged changes
git reset
# Create, fetch a remote branch and switch to it
git checkout --track <remote>/<branch>
# Remove a file from git but not from disc
git rm --cached <file>
# Reapply an old commit again
git cherry-pick <commit>
# Ignore the changes of a file
git update-index --assume-unchanged <file>
# Not ignore the changes of a file
git update-index --no-assume-unchanged <file>
# List all "assume-unchanged" files
git ls-files -v|grep '^h'
# Display who did the latest change in each line (ignoring whitespaces)
git blame <filename> -w
# Remove all local branches removed in remote
git fetch origin --prune
# Remove untracked local files
git clean -f
# Remove untracked local files and folders
git clean -fd
# Remove remote branch
git push <remote> --delete <branch>
# Go to an old commit
git read-tree <commit>
# Use the ~/.gitignore file to ignore globally certain files
git config --global core.excludesfile '~/.gitignore'
', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => 'GitHub Gist: instantly share code, notes, and snippets.', + 'favicon' => 'https://github.githubassets.com/favicons/favicon.svg', + 'feeds' => [ + 'https://gist.github.com/oscarotero.atom' + ], + 'icon' => null, + 'image' => 'https://github.githubassets.com/assets/gist-og-image-54fd7dc0713e.png', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Gist', + 'providerUrl' => 'https://gist.github.com/', + 'publishedTime' => '2013-12-02 14:10:20', + 'redirect' => null, + 'title' => 'Git-cheatsheet.sh', + 'url' => 'https://gist.github.com/oscarotero/7749998', + 'linkedData' => [], + 'oEmbed' => [], + 'api' => [ + 'description' => '', + 'public' => true, + 'created_at' => '2013-12-02T14:10:20.000Z', + 'files' => [ + 'Git-cheatsheet.sh' + ], + 'owner' => 'oscarotero', + 'div' => '
+
+
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
# Undo latest commit
git reset --soft HEAD^
+
# Undo the changes of a commit (creating a new commit)
git revert <commit>
+
# Undo latest merge (before push)
git reset --merge ORIG_HEAD
+
# Merge a branch using the version of the current branch in case of conflicts
git merge <branch> -s ours
+
# Discard changes for a particular file after commit
git reset HEAD <file>
+
# Unstage the current staged changes
git reset
+
# Create, fetch a remote branch and switch to it
git checkout --track <remote>/<branch>
+
# Remove a file from git but not from disc
git rm --cached <file>
+
# Reapply an old commit again
git cherry-pick <commit>
+
# Ignore the changes of a file
git update-index --assume-unchanged <file>
+
# Not ignore the changes of a file
git update-index --no-assume-unchanged <file>
+
# List all "assume-unchanged" files
git ls-files -v|grep '^h'
+
# Display who did the latest change in each line (ignoring whitespaces)
git blame <filename> -w
+
# Remove all local branches removed in remote
git fetch origin --prune
+
# Remove untracked local files
git clean -f
+
# Remove untracked local files and folders
git clean -fd
+
# Remove remote branch
git push <remote> --delete <branch>
+
# Go to an old commit
git read-tree <commit>
+
# Use the ~/.gitignore file to ignore globally certain files
git config --global core.excludesfile '~/.gitignore'
+
+ + +
+ +
+
+ +
+
+ view raw + + Git-cheatsheet.sh + + hosted with ❤ by GitHub +
+
+
+', + 'stylesheet' => 'https://github.githubassets.com/assets/gist-embed-8c1a5bab9782.css' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/github.com.benbalter-dc-wifi-social-blob-master-bars.geojson.php b/tests/fixtures/github.com.benbalter-dc-wifi-social-blob-master-bars.geojson.php new file mode 100644 index 00000000..92119322 --- /dev/null +++ b/tests/fixtures/github.com.benbalter-dc-wifi-social-blob-master-bars.geojson.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => 'A collaborative list of DC locations that serve up both Internet and Alcohol - benbalter/dc-wifi-social', + 'favicon' => 'https://github.githubassets.com/favicons/favicon.svg', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://avatars.githubusercontent.com/u/282759?s=400&v=4', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'GitHub', + 'providerUrl' => 'https://github.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'benbalter/dc-wifi-social', + 'url' => 'https://github.com/benbalter/dc-wifi-social/blob/master/bars.geojson', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/github.com.oscarotero-embed-blob-master-composer.json.php b/tests/fixtures/github.com.oscarotero-embed-blob-master-composer.json.php new file mode 100644 index 00000000..7cbbbb4b --- /dev/null +++ b/tests/fixtures/github.com.oscarotero-embed-blob-master-composer.json.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Get info from any web service or page. Contribute to oscarotero/Embed development by creating an account on GitHub.', + 'favicon' => 'https://github.githubassets.com/favicons/favicon.svg', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://avatars.githubusercontent.com/u/377873?s=400&v=4', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'GitHub', + 'providerUrl' => 'https://github.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'oscarotero/Embed', + 'url' => 'https://github.com/oscarotero/Embed/blob/master/composer.json', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/github.com.skalnik-secret-bear-clip-blob-master-stl-clip.stl.php b/tests/fixtures/github.com.skalnik-secret-bear-clip-blob-master-stl-clip.stl.php new file mode 100644 index 00000000..b76c9dac --- /dev/null +++ b/tests/fixtures/github.com.skalnik-secret-bear-clip-blob-master-stl-clip.stl.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => 'A clip to hold the Gooseneck Hue HD cameras to the Replicator 2 - skalnik/secret-bear-clip', + 'favicon' => 'https://github.githubassets.com/favicons/favicon.svg', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://avatars.githubusercontent.com/u/2546?s=400&v=4', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'GitHub', + 'providerUrl' => 'https://github.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'skalnik/secret-bear-clip', + 'url' => 'https://github.com/skalnik/secret-bear-clip/blob/master/stl/clip.stl', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/he-who-photographs-rather-ok.tumblr.com.post-165326273724.php b/tests/fixtures/he-who-photographs-rather-ok.tumblr.com.post-165326273724.php new file mode 100644 index 00000000..cc8f6852 --- /dev/null +++ b/tests/fixtures/he-who-photographs-rather-ok.tumblr.com.post-165326273724.php @@ -0,0 +1,70 @@ + 'He-who-photographs-rather-OK', + 'authorUrl' => 'https://www.tumblr.com/he-who-photographs-rather-ok', + 'cms' => null, + 'code' => [ + 'html' => '
https://www.tumblr.com/he-who-photographs-rather-ok/165326273724
', + 'width' => 540, + 'height' => null, + 'ratio' => null + ], + 'description' => 'Usually minimal editing. Also effort', + 'favicon' => 'https://64.media.tumblr.com/avatar_235be11f6ae4_128.pnj', + 'feeds' => [ + 'https://he-who-photographs-rather-ok.tumblr.com/rss' + ], + 'icon' => 'https://64.media.tumblr.com/avatar_235be11f6ae4_128.pnj', + 'image' => 'https://64.media.tumblr.com/0a0fac1ef8faa0c466d9224567af06aa/tumblr_ow8r0nMybA1spmyulo1_1280.jpg', + 'keywords' => [ + 'panda', + 'aesthetic photography', + 'furry', + 'photography', + 'photographers on tumblr' + ], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Tumblr', + 'providerUrl' => 'https://www.tumblr.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'He-who-photographs-rather-OK', + 'url' => 'https://www.tumblr.com/he-who-photographs-rather-ok/165326273724', + 'linkedData' => [ + '@type' => 'SocialMediaPosting', + 'url' => 'https://he-who-photographs-rather-ok.tumblr.com/post/165326273724', + 'mainEntityOfPage' => true, + 'datePublished' => '2017-09-14T10:20:35+00:00', + 'author' => 'he-who-photographs-rather-ok', + 'image' => 'https://64.media.tumblr.com/0a0fac1ef8faa0c466d9224567af06aa/tumblr_ow8r0nMybA1spmyulo1_1280.jpg', + '@context' => 'http://schema.org/' + ], + 'oEmbed' => [ + 'cache_age' => 3600, + 'url' => 'https://www.tumblr.com/he-who-photographs-rather-ok/165326273724', + 'provider_url' => 'https://www.tumblr.com/', + 'provider_name' => 'Tumblr', + 'author_name' => 'He-who-photographs-rather-OK', + 'version' => '1.0', + 'author_url' => 'https://www.tumblr.com/he-who-photographs-rather-ok', + 'type' => 'rich', + 'html' => '
https://www.tumblr.com/he-who-photographs-rather-ok/165326273724
', + 'height' => null, + 'width' => 540 + ], + 'allLinkedData' => [ + [ + '@type' => 'SocialMediaPosting', + 'url' => 'https://he-who-photographs-rather-ok.tumblr.com/post/165326273724', + 'mainEntityOfPage' => true, + 'datePublished' => '2017-09-14T10:20:35+00:00', + 'author' => 'he-who-photographs-rather-ok', + 'image' => 'https://64.media.tumblr.com/0a0fac1ef8faa0c466d9224567af06aa/tumblr_ow8r0nMybA1spmyulo1_1280.jpg', + '@context' => 'http://schema.org/' + ] + ] +]; diff --git a/tests/fixtures/i.imgur.com.x6rkcc5.jpg.php b/tests/fixtures/i.imgur.com.x6rkcc5.jpg.php new file mode 100644 index 00000000..523fd36f --- /dev/null +++ b/tests/fixtures/i.imgur.com.x6rkcc5.jpg.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'https://i.imgur.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://i.imgur.com/X6rkCc5.jpg', + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Imgur', + 'providerUrl' => 'https://i.imgur.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => null, + 'url' => 'https://i.imgur.com/X6rkCc5.jpg', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/ideone.com.whjntg.php b/tests/fixtures/ideone.com.whjntg.php new file mode 100644 index 00000000..3a6c938a --- /dev/null +++ b/tests/fixtures/ideone.com.whjntg.php @@ -0,0 +1,49 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => 'Ideone is something more than a pastebin; it\'s an online compiler and debugging tool which allows to compile and run code online in more than 40 programming languages.', + 'favicon' => 'https://d2c5ubcnqbm27w.cloudfront.net/gfx2/img/favicon.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'http://profile.ak.fbcdn.net/hprofile-ak-prn1/50232_245768360841_3377786_q.jpg', + 'keywords' => [ + 'online compiler', + 'online ide', + 'learn programming online', + 'programming online', + 'run code online', + 'snippet', + 'snippets', + 'pastebin', + 'online debugging tool', + 'online interpreter', + 'run your code online', + 'run code', + 'execute code', + 'c++', + 'java', + 'python' + ], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Ideone.com', + 'providerUrl' => 'https://ideone.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Ideone.com', + 'url' => 'https://ideone.com/Whjntg', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/imageshack.com.i-ip7wo0v7j.php b/tests/fixtures/imageshack.com.i-ip7wo0v7j.php new file mode 100644 index 00000000..5c737525 --- /dev/null +++ b/tests/fixtures/imageshack.com.i-ip7wo0v7j.php @@ -0,0 +1,78 @@ + 'ToddGilbert', + 'authorUrl' => 'https://imageshack.com/ToddGilbert', + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://imagizer.imageshack.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://imagizer.imageshack.com/img673/0/imagizer.imageshack.com/img673/9643/7wO0v7.jpg', + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'ImageShack', + 'providerUrl' => 'https://imagizer.imageshack.com/', + 'publishedTime' => '2015-06-29 22:13:36', + 'redirect' => null, + 'title' => 'Kisses', + 'url' => 'https://imagizer.imageshack.com/img673/0/7wO0v7.jpg', + 'linkedData' => [], + 'oEmbed' => [], + 'api' => [ + 'id' => 'ip7wO0v7j', + 'server' => 673, + 'bucket' => 9643, + 'filename' => '7wO0v7.jpg', + 'original_filename' => '249738f8eead6a9fa0cd4a17244ba418.jpg', + 'direct_link' => 'imagizer.imageshack.com/img673/9643/7wO0v7.jpg', + 'title' => 'Kisses', + 'description' => '', + 'tags' => [], + 'likes' => 0, + 'liked' => false, + 'views' => 0, + 'moderated' => false, + 'adult_content' => false, + 'album' => [ + 'id' => '', + 'title' => '', + 'public' => false + ], + 'comments_count' => 0, + 'comments_disabled' => true, + 'filter' => 0, + 'filesize' => 54, + 'creation_date' => 1435616016, + 'width' => 500, + 'height' => 500, + 'public' => true, + 'block_downloading' => false, + 'featured' => false, + 'copyright' => '', + 'is_owner' => false, + 'owner' => [ + 'username' => 'ToddGilbert', + 'avatar' => [ + 'id' => '59urlsij', + 'filename' => 'urlsi.jpg', + 'server' => 189, + 'cropped' => false, + 'x_pos' => 0, + 'y_pos' => 0, + 'x_length' => 0, + 'y_length' => 0 + ], + 'membership' => 'free', + 'featured_photographer' => false, + 'allow_following' => false + ], + 'next_images' => [], + 'prev_images' => [] + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/infogr.am.7743c36a-f3ca-4465-9a80-a8abbd5d8dc4.php b/tests/fixtures/infogr.am.7743c36a-f3ca-4465-9a80-a8abbd5d8dc4.php new file mode 100644 index 00000000..184ae35a --- /dev/null +++ b/tests/fixtures/infogr.am.7743c36a-f3ca-4465-9a80-a8abbd5d8dc4.php @@ -0,0 +1,46 @@ + 'Archive', + 'authorUrl' => 'https://infogram.com/archivef', + 'cms' => null, + 'code' => [ + 'html' => '
', + 'width' => 550, + 'height' => 600, + 'ratio' => 109.091 + ], + 'description' => null, + 'favicon' => 'https://cdn.jifo.co/favicon/favicon.ico?v=2', + 'feeds' => [], + 'icon' => 'https://cdn.jifo.co/favicon/apple-touch-icon.png', + 'image' => 'https://infogram-thumbs-1024.s3-eu-west-1.amazonaws.com/4e31a649-39af-4bfd-a6a9-384e727e36e2.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Infogram', + 'providerUrl' => 'https://infogram.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Frost Bank Advisors (online graphic)', + 'url' => 'https://infogram.com/7743c36a-f3ca-4465-9a80-a8abbd5d8dc4', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'rich', + 'provider_url' => 'https://infogram.com/', + 'provider_name' => 'Infogram', + 'description' => '', + 'title' => 'Frost Bank Advisors (online graphic)', + 'thumbnail_url' => 'https://infogram-thumbs-1024.s3-eu-west-1.amazonaws.com/4e31a649-39af-4bfd-a6a9-384e727e36e2.jpg', + 'uri' => 'https://infogram.com/frost-bank-advisors-online-graphic-1g8e205xdj03pod', + 'html' => '
', + 'width' => 550, + 'height' => 600, + 'author_url' => 'https://infogram.com/archivef', + 'author_name' => 'Archive' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/jeanjean.bandcamp.com.track-coquin-l-l-phant.php b/tests/fixtures/jeanjean.bandcamp.com.track-coquin-l-l-phant.php new file mode 100644 index 00000000..2e8ad133 --- /dev/null +++ b/tests/fixtures/jeanjean.bandcamp.com.track-coquin-l-l-phant.php @@ -0,0 +1,747 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 350, + 'height' => 467, + 'ratio' => 133.429 + ], + 'description' => 'from the album Symmetry', + 'favicon' => 'https://f4.bcbits.com/img/a3289609405_3.jpg', + 'feeds' => [], + 'icon' => 'https://f4.bcbits.com/img/a3289609405_3.jpg', + 'image' => 'https://f4.bcbits.com/img/a3289609405_5.jpg', + 'keywords' => [ + 'rock', + 'ambient', + 'electro-rock', + 'instrumental', + 'interstellar', + 'sept sorts' + ], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Bandcamp', + 'providerUrl' => 'https://jeanjean.bandcamp.com/', + 'publishedTime' => '2013-09-14 00:00:00', + 'redirect' => null, + 'title' => 'Coquin L\'éléphant, by Jean Jean', + 'url' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + 'linkedData' => [ + '@type' => 'MusicRecording', + '@id' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'track_id', + 'value' => 2592086951 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'art_id', + 'value' => 3289609405 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'license_name', + 'value' => 'all_rights_reserved' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'tracknum', + 'value' => 1 + ] + ], + 'name' => 'Coquin L\'éléphant', + 'duration' => 'P00H03M46S', + 'dateModified' => '13 Sep 2013 18:03:29 GMT', + 'datePublished' => '14 Sep 2013 00:00:00 GMT', + 'inAlbum' => [ + '@type' => 'MusicAlbum', + 'name' => 'Symmetry', + 'albumRelease' => [ + [ + '@type' => 'MusicRelease', + '@id' => 'https://jeanjean.bandcamp.com/album/symmetry', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'item_type', + 'value' => 'a' + ] + ] + ], + [ + '@type' => [ + 'MusicRelease', + 'Product' + ], + '@id' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + 'name' => 'Coquin L\'éléphant', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'item_id', + 'value' => 2592086951 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'item_type', + 'value' => 't' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'selling_band_id', + 'value' => 1235691216 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'type_name', + 'value' => 'Digital' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'art_id', + 'value' => 3289609405 + ] + ], + 'description' => 'Includes high-quality download in MP3, FLAC and more. Paying supporters also get unlimited streaming via the free Bandcamp app.', + 'offers' => [ + '@type' => 'Offer', + 'url' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant#t2592086951-buy', + 'priceCurrency' => 'EUR', + 'price' => 1.0, + 'priceSpecification' => [ + 'minPrice' => 1.0 + ], + 'availability' => 'OnlineOnly' + ], + 'musicReleaseFormat' => 'DigitalFormat', + 'image' => [ + 'https://f4.bcbits.com/img/a3289609405_10.jpg' + ] + ], + [ + '@type' => [ + 'MusicRelease', + 'Product' + ], + '@id' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant#p1271421079', + 'name' => '12" Vinyl', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'item_id', + 'value' => 1271421079 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'item_type', + 'value' => 'p' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'selling_band_id', + 'value' => 1235691216 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'type_name', + 'value' => 'Vinyl LP' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_ids', + 'value' => [ + 1822625 + ] + ], + [ + '@type' => 'PropertyValue', + 'name' => 'is_music_merch', + 'value' => true + ], + [ + '@type' => 'PropertyValue', + 'name' => 'type_id', + 'value' => 2 + ] + ], + 'offers' => [ + '@type' => 'Offer', + 'url' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant#p1271421079-buy', + 'priceCurrency' => 'EUR', + 'price' => 12.0, + 'priceSpecification' => [ + 'minPrice' => 12.0 + ], + 'availability' => 'SoldOut', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'includes_digital_download', + 'value' => true + ] + ] + ], + 'musicReleaseFormat' => 'VinylFormat', + 'image' => [ + 'https://f4.bcbits.com/img/0001822625_10.jpg' + ] + ] + ], + 'albumReleaseType' => 'SingleRelease', + '@id' => 'https://jeanjean.bandcamp.com/album/symmetry', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'download_pref', + 'value' => 2 + ] + ] + ], + 'byArtist' => [ + '@type' => 'MusicGroup', + 'name' => 'Jean Jean', + '@id' => 'https://jeanjean.bandcamp.com/' + ], + 'publisher' => [ + '@type' => 'MusicGroup', + '@id' => 'https://jeanjean.bandcamp.com/', + 'name' => 'Jean Jean', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'band_id', + 'value' => 1235691216 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'has_any_downloads', + 'value' => true + ], + [ + '@type' => 'PropertyValue', + 'name' => 'has_download_codes', + 'value' => true + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_height', + 'value' => 1600 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 29836714 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_width', + 'value' => 2279 + ] + ], + 'image' => 'https://f4.bcbits.com/img/0029836714_10.jpg', + 'genre' => 'https://bandcamp.com/discover/rock', + 'description' => '« On stage, JEAN JEAN is a mirror to their music : deeply intense, smiling and sharing an outra- geous joie-de-vivre. It all seems so simple, but when it builds up, they take you far, very far away » (Christophe Ehrwein)', + 'mainEntityOfPage' => [ + [ + '@type' => 'WebPage', + 'url' => 'http://www.facebook.com/jeanjeanmusic', + 'name' => 'Facebook' + ], + [ + '@type' => 'WebPage', + 'url' => 'https://www.instagram.com/wearejeanjean/', + 'name' => 'Instagram' + ], + [ + '@type' => 'WebPage', + 'url' => 'http://www.youtube.com/channel/UCOsMtEsuiqbqkFQ9oyqJhHg', + 'name' => 'YouTube' + ], + [ + '@type' => 'WebPage', + 'url' => 'http://jeanjeanband.com/', + 'name' => 'jeanjeanband.com' + ], + [ + '@type' => 'WebPage', + 'url' => 'https://twitter.com/jeanjeanband', + 'name' => 'Twitter' + ] + ], + 'subjectOf' => [ + [ + '@type' => 'WebPage', + 'url' => 'https://jeanjean.bandcamp.com/music', + 'name' => 'music', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'nav_type', + 'value' => 'm' + ] + ] + ], + [ + '@type' => 'WebPage', + 'url' => 'https://jeanjean.bandcamp.com/merch', + 'name' => 'merch', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'nav_type', + 'value' => 'p' + ] + ] + ], + [ + '@type' => 'WebPage', + 'url' => 'https://jeanjean.bandcamp.com/community', + 'name' => 'community', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'nav_type', + 'value' => 'c' + ] + ] + ] + ], + 'foundingLocation' => [ + '@type' => 'Place', + 'name' => 'Sept Sorts, France' + ] + ], + 'copyrightNotice' => 'All Rights Reserved', + 'keywords' => [ + 'Rock', + 'ambient', + 'electro-rock', + 'instrumental', + 'interstellar', + 'Sept Sorts' + ], + 'image' => 'https://f4.bcbits.com/img/a3289609405_10.jpg', + 'sponsor' => [ + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/jaredremillard', + 'image' => 'https://f4.bcbits.com/img/0001850798_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 1850798 + ] + ], + 'name' => 'Jared ReMillard' + ], + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/sheebypanda', + 'image' => 'https://f4.bcbits.com/img/0004764347_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 4764347 + ] + ], + 'name' => 'SheebyPanda' + ], + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/salvajer911', + 'image' => 'https://f4.bcbits.com/img/0017750248_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 17750248 + ] + ], + 'name' => 'Guilhem Sauvage' + ], + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/tylerthornhill', + 'image' => 'https://f4.bcbits.com/img/0001705921_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 1705921 + ] + ], + 'name' => 'Tyler Thornhill' + ] + ], + 'mainEntityOfPage' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + '@context' => 'https://schema.org/' + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@type' => 'MusicRecording', + '@id' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'track_id', + 'value' => 2592086951 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'art_id', + 'value' => 3289609405 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'license_name', + 'value' => 'all_rights_reserved' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'tracknum', + 'value' => 1 + ] + ], + 'name' => 'Coquin L\'éléphant', + 'duration' => 'P00H03M46S', + 'dateModified' => '13 Sep 2013 18:03:29 GMT', + 'datePublished' => '14 Sep 2013 00:00:00 GMT', + 'inAlbum' => [ + '@type' => 'MusicAlbum', + 'name' => 'Symmetry', + 'albumRelease' => [ + [ + '@type' => 'MusicRelease', + '@id' => 'https://jeanjean.bandcamp.com/album/symmetry', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'item_type', + 'value' => 'a' + ] + ] + ], + [ + '@type' => [ + 'MusicRelease', + 'Product' + ], + '@id' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + 'name' => 'Coquin L\'éléphant', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'item_id', + 'value' => 2592086951 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'item_type', + 'value' => 't' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'selling_band_id', + 'value' => 1235691216 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'type_name', + 'value' => 'Digital' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'art_id', + 'value' => 3289609405 + ] + ], + 'description' => 'Includes high-quality download in MP3, FLAC and more. Paying supporters also get unlimited streaming via the free Bandcamp app.', + 'offers' => [ + '@type' => 'Offer', + 'url' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant#t2592086951-buy', + 'priceCurrency' => 'EUR', + 'price' => 1.0, + 'priceSpecification' => [ + 'minPrice' => 1.0 + ], + 'availability' => 'OnlineOnly' + ], + 'musicReleaseFormat' => 'DigitalFormat', + 'image' => [ + 'https://f4.bcbits.com/img/a3289609405_10.jpg' + ] + ], + [ + '@type' => [ + 'MusicRelease', + 'Product' + ], + '@id' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant#p1271421079', + 'name' => '12" Vinyl', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'item_id', + 'value' => 1271421079 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'item_type', + 'value' => 'p' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'selling_band_id', + 'value' => 1235691216 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'type_name', + 'value' => 'Vinyl LP' + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_ids', + 'value' => [ + 1822625 + ] + ], + [ + '@type' => 'PropertyValue', + 'name' => 'is_music_merch', + 'value' => true + ], + [ + '@type' => 'PropertyValue', + 'name' => 'type_id', + 'value' => 2 + ] + ], + 'offers' => [ + '@type' => 'Offer', + 'url' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant#p1271421079-buy', + 'priceCurrency' => 'EUR', + 'price' => 12.0, + 'priceSpecification' => [ + 'minPrice' => 12.0 + ], + 'availability' => 'SoldOut', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'includes_digital_download', + 'value' => true + ] + ] + ], + 'musicReleaseFormat' => 'VinylFormat', + 'image' => [ + 'https://f4.bcbits.com/img/0001822625_10.jpg' + ] + ] + ], + 'albumReleaseType' => 'SingleRelease', + '@id' => 'https://jeanjean.bandcamp.com/album/symmetry', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'download_pref', + 'value' => 2 + ] + ] + ], + 'byArtist' => [ + '@type' => 'MusicGroup', + 'name' => 'Jean Jean', + '@id' => 'https://jeanjean.bandcamp.com/' + ], + 'publisher' => [ + '@type' => 'MusicGroup', + '@id' => 'https://jeanjean.bandcamp.com/', + 'name' => 'Jean Jean', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'band_id', + 'value' => 1235691216 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'has_any_downloads', + 'value' => true + ], + [ + '@type' => 'PropertyValue', + 'name' => 'has_download_codes', + 'value' => true + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_height', + 'value' => 1600 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 29836714 + ], + [ + '@type' => 'PropertyValue', + 'name' => 'image_width', + 'value' => 2279 + ] + ], + 'image' => 'https://f4.bcbits.com/img/0029836714_10.jpg', + 'genre' => 'https://bandcamp.com/discover/rock', + 'description' => '« On stage, JEAN JEAN is a mirror to their music : deeply intense, smiling and sharing an outra- geous joie-de-vivre. It all seems so simple, but when it builds up, they take you far, very far away » (Christophe Ehrwein)', + 'mainEntityOfPage' => [ + [ + '@type' => 'WebPage', + 'url' => 'http://www.facebook.com/jeanjeanmusic', + 'name' => 'Facebook' + ], + [ + '@type' => 'WebPage', + 'url' => 'https://www.instagram.com/wearejeanjean/', + 'name' => 'Instagram' + ], + [ + '@type' => 'WebPage', + 'url' => 'http://www.youtube.com/channel/UCOsMtEsuiqbqkFQ9oyqJhHg', + 'name' => 'YouTube' + ], + [ + '@type' => 'WebPage', + 'url' => 'http://jeanjeanband.com/', + 'name' => 'jeanjeanband.com' + ], + [ + '@type' => 'WebPage', + 'url' => 'https://twitter.com/jeanjeanband', + 'name' => 'Twitter' + ] + ], + 'subjectOf' => [ + [ + '@type' => 'WebPage', + 'url' => 'https://jeanjean.bandcamp.com/music', + 'name' => 'music', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'nav_type', + 'value' => 'm' + ] + ] + ], + [ + '@type' => 'WebPage', + 'url' => 'https://jeanjean.bandcamp.com/merch', + 'name' => 'merch', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'nav_type', + 'value' => 'p' + ] + ] + ], + [ + '@type' => 'WebPage', + 'url' => 'https://jeanjean.bandcamp.com/community', + 'name' => 'community', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'nav_type', + 'value' => 'c' + ] + ] + ] + ], + 'foundingLocation' => [ + '@type' => 'Place', + 'name' => 'Sept Sorts, France' + ] + ], + 'copyrightNotice' => 'All Rights Reserved', + 'keywords' => [ + 'Rock', + 'ambient', + 'electro-rock', + 'instrumental', + 'interstellar', + 'Sept Sorts' + ], + 'image' => 'https://f4.bcbits.com/img/a3289609405_10.jpg', + 'sponsor' => [ + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/jaredremillard', + 'image' => 'https://f4.bcbits.com/img/0001850798_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 1850798 + ] + ], + 'name' => 'Jared ReMillard' + ], + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/sheebypanda', + 'image' => 'https://f4.bcbits.com/img/0004764347_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 4764347 + ] + ], + 'name' => 'SheebyPanda' + ], + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/salvajer911', + 'image' => 'https://f4.bcbits.com/img/0017750248_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 17750248 + ] + ], + 'name' => 'Guilhem Sauvage' + ], + [ + '@type' => 'Person', + 'url' => 'https://bandcamp.com/tylerthornhill', + 'image' => 'https://f4.bcbits.com/img/0001705921_50.jpg', + 'additionalProperty' => [ + [ + '@type' => 'PropertyValue', + 'name' => 'image_id', + 'value' => 1705921 + ] + ], + 'name' => 'Tyler Thornhill' + ] + ], + 'mainEntityOfPage' => 'https://jeanjean.bandcamp.com/track/coquin-l-l-phant', + '@context' => 'https://schema.org/' + ] + ] +]; diff --git a/tests/fixtures/jsfiddle.net.zhm5rjnz.php b/tests/fixtures/jsfiddle.net.zhm5rjnz.php new file mode 100644 index 00000000..5edf5fa6 --- /dev/null +++ b/tests/fixtures/jsfiddle.net.zhm5rjnz.php @@ -0,0 +1,36 @@ + 'JSFiddle', + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code editor.', + 'favicon' => 'https://jsfiddle.net/img/favicon.png', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [ + 'online javascript editor', + 'testing javascript online', + 'online ide', + 'online code editor', + 'html', + 'css', + 'coffeescript', + 'scss online editor' + ], + 'language' => null, + 'languages' => [], + 'license' => 'share alike', + 'providerName' => 'Jsfiddle', + 'providerUrl' => 'https://jsfiddle.net/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Edit fiddle - JSFiddle - Code Playground', + 'url' => 'https://jsfiddle.net/zhm5rjnz/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/live.amcharts.com.cznjj.php b/tests/fixtures/live.amcharts.com.cznjj.php new file mode 100644 index 00000000..f718e91a --- /dev/null +++ b/tests/fixtures/live.amcharts.com.cznjj.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'amCharts live editor: create, configure, tweak, edit data, export, import, save, share in a single interface, the user-friendly way.', + 'favicon' => 'https://live.amcharts.com/static/img/page/favicon.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://live.amcharts.com/static/img/page/editor-shot.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'amCharts', + 'providerUrl' => 'https://live.amcharts.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Live Chart Editor', + 'url' => 'https://live.amcharts.com/czNjJ/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/media.photobucket.com.user-ignwar-media-album-20deserts-moonrisemonumentvalleyutah.jpg.html.c07885ac4c85b35f31f6dc858d4d64b0.php b/tests/fixtures/media.photobucket.com.user-ignwar-media-album-20deserts-moonrisemonumentvalleyutah.jpg.html.c07885ac4c85b35f31f6dc858d4d64b0.php new file mode 100644 index 00000000..862a5c0c --- /dev/null +++ b/tests/fixtures/media.photobucket.com.user-ignwar-media-album-20deserts-moonrisemonumentvalleyutah.jpg.html.c07885ac4c85b35f31f6dc858d4d64b0.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Store your photos and videos online with secure storage from Photobucket. Available on iOS, Android and desktop. Securely backup your memories and sign up today!', + 'favicon' => 'https://media.photobucket.com/favicon.ico', + 'feeds' => [], + 'icon' => 'https://media.photobucket.com/logo192.png', + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Photobucket', + 'providerUrl' => 'https://media.photobucket.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Photo Storage', + 'url' => 'https://media.photobucket.com/user/Ignwar/media/Album%20Deserts/MoonriseMonumentValleyUtah.jpg.html?filters%5Bterm%5D=sunsets&filters%5Bprimary%5D=images', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/open.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php b/tests/fixtures/open.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php new file mode 100644 index 00000000..52680753 --- /dev/null +++ b/tests/fixtures/open.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php @@ -0,0 +1,117 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 456, + 'height' => 352, + 'ratio' => 77.193 + ], + 'description' => 'Xabarin · Album · 1994 · 44 songs.', + 'favicon' => 'https://open.spotifycdn.com/cdn/images/favicon32.b64ecc03.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://i.scdn.co/image/ab67616d00001e022dd9ff41aad54c1d93d50aa6', + 'keywords' => [], + 'language' => 'en', + 'languages' => [ + 'x-default' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'en' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'id' => 'https://open.spotify.com/intl-id/album/7s66wU1XJ2NsUuWM2NKiUV', + 'de' => 'https://open.spotify.com/intl-de/album/7s66wU1XJ2NsUuWM2NKiUV', + 'pt' => 'https://open.spotify.com/intl-pt/album/7s66wU1XJ2NsUuWM2NKiUV', + 'ja' => 'https://open.spotify.com/intl-ja/album/7s66wU1XJ2NsUuWM2NKiUV', + 'fr' => 'https://open.spotify.com/intl-fr/album/7s66wU1XJ2NsUuWM2NKiUV', + 'ar' => 'https://open.spotify.com/intl-ar/album/7s66wU1XJ2NsUuWM2NKiUV', + 'es' => 'https://open.spotify.com/intl-es/album/7s66wU1XJ2NsUuWM2NKiUV', + 'tr' => 'https://open.spotify.com/intl-tr/album/7s66wU1XJ2NsUuWM2NKiUV', + 'it' => 'https://open.spotify.com/intl-it/album/7s66wU1XJ2NsUuWM2NKiUV' + ], + 'license' => null, + 'providerName' => 'Spotify', + 'providerUrl' => 'https://spotify.com/', + 'publishedTime' => '1994-03-01 00:00:00', + 'redirect' => null, + 'title' => 'A Cantar con Xabarin (Vol. I e II)', + 'url' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'linkedData' => [ + '@context' => 'http://schema.googleapis.com/', + '@type' => 'MusicAlbum', + '@id' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'url' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'name' => 'A Cantar con Xabarin (Vol. I e II)', + 'description' => 'Listen to A Cantar con Xabarin (Vol. I e II) on Spotify. Xabarin · Album · 1994 · 44 songs.', + 'datePublished' => '1994-03-01', + 'potentialAction' => [ + '@type' => 'ListenAction', + 'target' => [ + [ + '@type' => 'EntryPoint', + 'urlTemplate' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV?autoplay=true', + 'actionPlatform' => [ + 'http://schema.org/DesktopWebPlatform', + 'http://schema.org/IOSPlatform', + 'http://schema.googleapis.com/GoogleAudioCast', + 'http://schema.googleapis.com/GoogleVideoCast' + ] + ], + 'android-app://com.spotify.music/spotify/album/7s66wU1XJ2NsUuWM2NKiUV/play' + ], + 'expectsAcceptanceOf' => [ + '@type' => 'Offer', + 'category' => 'free', + 'eligibleRegion' => [] + ] + ] + ], + 'oEmbed' => [ + 'html' => '', + 'iframe_url' => 'https://open.spotify.com/embed/album/7s66wU1XJ2NsUuWM2NKiUV?utm_source=oembed', + 'width' => 456, + 'height' => 352, + 'version' => '1.0', + 'provider_name' => 'Spotify', + 'provider_url' => 'https://spotify.com/', + 'type' => 'rich', + 'title' => 'A Cantar con Xabarin (Vol. I e II)', + 'thumbnail_url' => 'https://i.scdn.co/image/ab67616d00001e022dd9ff41aad54c1d93d50aa6', + 'thumbnail_width' => 300, + 'thumbnail_height' => 300 + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.googleapis.com/', + '@type' => 'MusicAlbum', + '@id' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'url' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'name' => 'A Cantar con Xabarin (Vol. I e II)', + 'description' => 'Listen to A Cantar con Xabarin (Vol. I e II) on Spotify. Xabarin · Album · 1994 · 44 songs.', + 'datePublished' => '1994-03-01', + 'potentialAction' => [ + '@type' => 'ListenAction', + 'target' => [ + [ + '@type' => 'EntryPoint', + 'urlTemplate' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV?autoplay=true', + 'actionPlatform' => [ + 'http://schema.org/DesktopWebPlatform', + 'http://schema.org/IOSPlatform', + 'http://schema.googleapis.com/GoogleAudioCast', + 'http://schema.googleapis.com/GoogleVideoCast' + ] + ], + 'android-app://com.spotify.music/spotify/album/7s66wU1XJ2NsUuWM2NKiUV/play' + ], + 'expectsAcceptanceOf' => [ + '@type' => 'Offer', + 'category' => 'free', + 'eligibleRegion' => [] + ] + ] + ] + ] +]; diff --git a/tests/fixtures/output.jsbin.com.vonesu-10.php b/tests/fixtures/output.jsbin.com.vonesu-10.php new file mode 100644 index 00000000..9336f167 --- /dev/null +++ b/tests/fixtures/output.jsbin.com.vonesu-10.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'http://output.jsbin.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Jsbin', + 'providerUrl' => 'http://output.jsbin.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'JS Bin', + 'url' => 'http://output.jsbin.com/vonesu/10', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/pachunka.deviantart.com.art-cope-145564099.php b/tests/fixtures/pachunka.deviantart.com.art-cope-145564099.php new file mode 100644 index 00000000..c67c22f7 --- /dev/null +++ b/tests/fixtures/pachunka.deviantart.com.art-cope-145564099.php @@ -0,0 +1,66 @@ + 'pachunka', + 'authorUrl' => 'https://www.deviantart.com/pachunka', + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://st.deviantart.net/eclipse/icons/da_favicon_v2.ico', + 'feeds' => [], + 'icon' => 'https://st.deviantart.net/eclipse/icons/ios-180.png', + 'image' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2b5a457d-dde7-459a-badf-774e8e506025/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg/v1/fit/w_300,h_672,q_70,strp/cope_by_pachunka_d2enxz7-300w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'DeviantArt', + 'providerUrl' => 'https://www.deviantart.com/', + 'publishedTime' => '2009-12-02 23:59:51', + 'redirect' => null, + 'title' => 'Cope', + 'url' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2b5a457d-dde7-459a-badf-774e8e506025/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzJiNWE0NTdkLWRkZTctNDU5YS1iYWRmLTc3NGU4ZTUwNjAyNVwvZDJlbnh6Ny00MzFjYTljMy05ODdmLTRiMmQtYWU2YS1jYmJkZDFjMGUyYmYuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.pCEF4M_tMVZI92ZKClZdcMu5UqpQ3131DrHsx1WxefY', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'photo', + 'title' => 'Cope', + 'category' => 'Digital Art > Drawings & Paintings > Illustrations > Conceptual', + 'url' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2b5a457d-dde7-459a-badf-774e8e506025/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzJiNWE0NTdkLWRkZTctNDU5YS1iYWRmLTc3NGU4ZTUwNjAyNVwvZDJlbnh6Ny00MzFjYTljMy05ODdmLTRiMmQtYWU2YS1jYmJkZDFjMGUyYmYuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.pCEF4M_tMVZI92ZKClZdcMu5UqpQ3131DrHsx1WxefY', + 'author_name' => 'pachunka', + 'author_url' => 'https://www.deviantart.com/pachunka', + 'provider_name' => 'DeviantArt', + 'provider_url' => 'https://www.deviantart.com/', + 'safety' => 'nonadult', + 'pubdate' => '2009-12-02T23:59:51-08:00', + 'community' => [ + 'statistics' => [ + '_attributes' => [ + 'views' => 3279, + 'favorites' => 10, + 'comments' => 5, + 'downloads' => 63 + ] + ] + ], + 'copyright' => [ + '_attributes' => [ + 'url' => 'https://www.deviantart.com/pachunka', + 'year' => '2009', + 'entity' => 'pachunka' + ] + ], + 'width' => '448', + 'height' => '672', + 'imagetype' => 'jpg', + 'thumbnail_url' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2b5a457d-dde7-459a-badf-774e8e506025/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg/v1/fit/w_300,h_672,q_70,strp/cope_by_pachunka_d2enxz7-300w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8', + 'thumbnail_width' => 300, + 'thumbnail_height' => 450, + 'thumbnail_url_150' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2b5a457d-dde7-459a-badf-774e8e506025/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg/v1/fit/w_150,h_150,q_70,strp/cope_by_pachunka_d2enxz7-150.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8', + 'thumbnail_url_200h' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2b5a457d-dde7-459a-badf-774e8e506025/d2enxz7-431ca9c3-987f-4b2d-ae6a-cbbdd1c0e2bf.jpg/v1/fill/w_133,h_200,q_70,strp/cope_by_pachunka_d2enxz7-200h.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9NjcyIiwicGF0aCI6IlwvZlwvMmI1YTQ1N2QtZGRlNy00NTlhLWJhZGYtNzc0ZThlNTA2MDI1XC9kMmVueHo3LTQzMWNhOWMzLTk4N2YtNGIyZC1hZTZhLWNiYmRkMWMwZTJiZi5qcGciLCJ3aWR0aCI6Ijw9NDQ4In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.IgIuTtYswRRSrLcUD8alCdW0sAgmkVTiQAjV5-OCfv8', + 'thumbnail_width_200h' => 133, + 'thumbnail_height_200h' => 200 + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/pastebin.com.d4biutrm.php b/tests/fixtures/pastebin.com.d4biutrm.php new file mode 100644 index 00000000..3489ba95 --- /dev/null +++ b/tests/fixtures/pastebin.com.d4biutrm.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.', + 'favicon' => 'https://pastebin.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://pastebin.com/i/facebook.png', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Pastebin', + 'providerUrl' => 'https://pastebin.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Pushing new git submodule to Heroku - Pastebin.com', + 'url' => 'https://pastebin.com/d4biUtRm', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/play.cadenaser.com.audio-001rd010000004275766.php b/tests/fixtures/play.cadenaser.com.audio-001rd010000004275766.php new file mode 100644 index 00000000..25eff819 --- /dev/null +++ b/tests/fixtures/play.cadenaser.com.audio-001rd010000004275766.php @@ -0,0 +1,71 @@ + 'Cadena SER', + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Ana Pontón, candidata del BNG; Xoaquín Fernández Leiceaga, candidato del PSdG-PSOE; Luis Villares, candidato de En Marea, y Pedro Puy, candidato del PP por A Coruña y coordinador del programa electoral de Alberto Núñez Feijoo debaten en Hoy por Hoy', + 'favicon' => 'https://cadenaser.com/pf/resources/img/favicon.png?d=1014', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://cadenaser.com/resizer/a9WQ8rJ3QL6pdxxPeqscG8rnPHU=/1200x630/smart/filters:quality(70)/urotrosfiles.media.streamtheworld.com/otrosfiles/objetos/logos/cadenaser-logo_01.png', + 'keywords' => [], + 'language' => 'es', + 'languages' => [], + 'license' => null, + 'providerName' => 'cadena SER', + 'providerUrl' => 'https://cadenaser.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Debate electoral gallego, en \'Hoy por Hoy\' | Cadena Ser', + 'url' => 'https://cadenaser.com/audio/001RD010000004275766/', + 'linkedData' => [ + '@context' => 'https://schema.org/', + '@type' => 'BreadcrumbList', + 'itemListElement' => [ + [ + '@type' => 'ListItem', + 'position' => 1, + 'item' => [ + '@id' => 'https://cadenaser.com/', + 'name' => 'Inicio' + ] + ], + [ + '@type' => 'ListItem', + 'position' => 2, + 'item' => [ + '@id' => 'https://cadenaser.com/audio/001RD010000004275766/', + 'name' => 'Audio 001RD010000004275766' + ] + ] + ] + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@context' => 'https://schema.org/', + '@type' => 'BreadcrumbList', + 'itemListElement' => [ + [ + '@type' => 'ListItem', + 'position' => 1, + 'item' => [ + '@id' => 'https://cadenaser.com/', + 'name' => 'Inicio' + ] + ], + [ + '@type' => 'ListItem', + 'position' => 2, + 'item' => [ + '@id' => 'https://cadenaser.com/audio/001RD010000004275766/', + 'name' => 'Audio 001RD010000004275766' + ] + ] + ] + ] + ] +]; diff --git a/tests/fixtures/play.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php b/tests/fixtures/play.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php new file mode 100644 index 00000000..29f18cc1 --- /dev/null +++ b/tests/fixtures/play.spotify.com.album-7s66wu1xj2nsuuwm2nkiuv.php @@ -0,0 +1,1530 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 456, + 'height' => 380, + 'ratio' => 83.333 + ], + 'description' => 'Various Artists · Compilation · 1996 · 44 songs.', + 'favicon' => 'https://open.scdn.co/cdn/images/favicon32.a19b4f5b.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://i.scdn.co/image/ab67616d00001e02022aca057f08a1d40c1f0733', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Spotify', + 'providerUrl' => 'https://spotify.com/', + 'publishedTime' => '1996-03-05 00:00:00', + 'redirect' => null, + 'title' => 'A Cantar con Xabarin (Vol. I & II)', + 'url' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'linkedData' => [ + '@context' => 'http://schema.googleapis.com/', + '@type' => 'MusicAlbum', + '@id' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'url' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'name' => 'A Cantar con Xabarin (Vol. I & II)', + 'description' => 'Listen to A Cantar con Xabarin (Vol. I & II) on Spotify. Various Artists · Compilation · 1996 · 44 songs.', + 'datePublished' => '1996-03-05', + 'potentialAction' => [ + '@type' => 'ListenAction', + 'target' => [ + [ + '@type' => 'EntryPoint', + 'urlTemplate' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV?autoplay=true', + 'actionPlatform' => [ + 'http://schema.org/DesktopWebPlatform', + 'http://schema.org/IOSPlatform', + 'http://schema.googleapis.com/GoogleAudioCast', + 'http://schema.googleapis.com/GoogleVideoCast' + ] + ], + 'android-app://com.spotify.music/spotify/album/7s66wU1XJ2NsUuWM2NKiUV/play' + ], + 'expectsAcceptanceOf' => [ + '@type' => 'Offer', + 'category' => 'free', + 'eligibleRegion' => [ + [ + '@type' => 'Country', + 'name' => 'AD' + ], + [ + '@type' => 'Country', + 'name' => 'AE' + ], + [ + '@type' => 'Country', + 'name' => 'AG' + ], + [ + '@type' => 'Country', + 'name' => 'AL' + ], + [ + '@type' => 'Country', + 'name' => 'AM' + ], + [ + '@type' => 'Country', + 'name' => 'AO' + ], + [ + '@type' => 'Country', + 'name' => 'AR' + ], + [ + '@type' => 'Country', + 'name' => 'AT' + ], + [ + '@type' => 'Country', + 'name' => 'AU' + ], + [ + '@type' => 'Country', + 'name' => 'AZ' + ], + [ + '@type' => 'Country', + 'name' => 'BA' + ], + [ + '@type' => 'Country', + 'name' => 'BB' + ], + [ + '@type' => 'Country', + 'name' => 'BD' + ], + [ + '@type' => 'Country', + 'name' => 'BE' + ], + [ + '@type' => 'Country', + 'name' => 'BF' + ], + [ + '@type' => 'Country', + 'name' => 'BG' + ], + [ + '@type' => 'Country', + 'name' => 'BH' + ], + [ + '@type' => 'Country', + 'name' => 'BI' + ], + [ + '@type' => 'Country', + 'name' => 'BJ' + ], + [ + '@type' => 'Country', + 'name' => 'BN' + ], + [ + '@type' => 'Country', + 'name' => 'BO' + ], + [ + '@type' => 'Country', + 'name' => 'BR' + ], + [ + '@type' => 'Country', + 'name' => 'BS' + ], + [ + '@type' => 'Country', + 'name' => 'BT' + ], + [ + '@type' => 'Country', + 'name' => 'BW' + ], + [ + '@type' => 'Country', + 'name' => 'BY' + ], + [ + '@type' => 'Country', + 'name' => 'BZ' + ], + [ + '@type' => 'Country', + 'name' => 'CA' + ], + [ + '@type' => 'Country', + 'name' => 'CH' + ], + [ + '@type' => 'Country', + 'name' => 'CI' + ], + [ + '@type' => 'Country', + 'name' => 'CL' + ], + [ + '@type' => 'Country', + 'name' => 'CM' + ], + [ + '@type' => 'Country', + 'name' => 'CO' + ], + [ + '@type' => 'Country', + 'name' => 'CR' + ], + [ + '@type' => 'Country', + 'name' => 'CV' + ], + [ + '@type' => 'Country', + 'name' => 'CW' + ], + [ + '@type' => 'Country', + 'name' => 'CY' + ], + [ + '@type' => 'Country', + 'name' => 'CZ' + ], + [ + '@type' => 'Country', + 'name' => 'DE' + ], + [ + '@type' => 'Country', + 'name' => 'DJ' + ], + [ + '@type' => 'Country', + 'name' => 'DK' + ], + [ + '@type' => 'Country', + 'name' => 'DM' + ], + [ + '@type' => 'Country', + 'name' => 'DO' + ], + [ + '@type' => 'Country', + 'name' => 'DZ' + ], + [ + '@type' => 'Country', + 'name' => 'EC' + ], + [ + '@type' => 'Country', + 'name' => 'EE' + ], + [ + '@type' => 'Country', + 'name' => 'EG' + ], + [ + '@type' => 'Country', + 'name' => 'ES' + ], + [ + '@type' => 'Country', + 'name' => 'FI' + ], + [ + '@type' => 'Country', + 'name' => 'FJ' + ], + [ + '@type' => 'Country', + 'name' => 'FM' + ], + [ + '@type' => 'Country', + 'name' => 'FR' + ], + [ + '@type' => 'Country', + 'name' => 'GA' + ], + [ + '@type' => 'Country', + 'name' => 'GB' + ], + [ + '@type' => 'Country', + 'name' => 'GD' + ], + [ + '@type' => 'Country', + 'name' => 'GE' + ], + [ + '@type' => 'Country', + 'name' => 'GH' + ], + [ + '@type' => 'Country', + 'name' => 'GM' + ], + [ + '@type' => 'Country', + 'name' => 'GN' + ], + [ + '@type' => 'Country', + 'name' => 'GQ' + ], + [ + '@type' => 'Country', + 'name' => 'GR' + ], + [ + '@type' => 'Country', + 'name' => 'GT' + ], + [ + '@type' => 'Country', + 'name' => 'GW' + ], + [ + '@type' => 'Country', + 'name' => 'GY' + ], + [ + '@type' => 'Country', + 'name' => 'HK' + ], + [ + '@type' => 'Country', + 'name' => 'HN' + ], + [ + '@type' => 'Country', + 'name' => 'HR' + ], + [ + '@type' => 'Country', + 'name' => 'HT' + ], + [ + '@type' => 'Country', + 'name' => 'HU' + ], + [ + '@type' => 'Country', + 'name' => 'ID' + ], + [ + '@type' => 'Country', + 'name' => 'IE' + ], + [ + '@type' => 'Country', + 'name' => 'IL' + ], + [ + '@type' => 'Country', + 'name' => 'IN' + ], + [ + '@type' => 'Country', + 'name' => 'IS' + ], + [ + '@type' => 'Country', + 'name' => 'IT' + ], + [ + '@type' => 'Country', + 'name' => 'JM' + ], + [ + '@type' => 'Country', + 'name' => 'JO' + ], + [ + '@type' => 'Country', + 'name' => 'JP' + ], + [ + '@type' => 'Country', + 'name' => 'KE' + ], + [ + '@type' => 'Country', + 'name' => 'KG' + ], + [ + '@type' => 'Country', + 'name' => 'KH' + ], + [ + '@type' => 'Country', + 'name' => 'KI' + ], + [ + '@type' => 'Country', + 'name' => 'KM' + ], + [ + '@type' => 'Country', + 'name' => 'KN' + ], + [ + '@type' => 'Country', + 'name' => 'KR' + ], + [ + '@type' => 'Country', + 'name' => 'KW' + ], + [ + '@type' => 'Country', + 'name' => 'KZ' + ], + [ + '@type' => 'Country', + 'name' => 'LA' + ], + [ + '@type' => 'Country', + 'name' => 'LB' + ], + [ + '@type' => 'Country', + 'name' => 'LC' + ], + [ + '@type' => 'Country', + 'name' => 'LI' + ], + [ + '@type' => 'Country', + 'name' => 'LK' + ], + [ + '@type' => 'Country', + 'name' => 'LR' + ], + [ + '@type' => 'Country', + 'name' => 'LS' + ], + [ + '@type' => 'Country', + 'name' => 'LT' + ], + [ + '@type' => 'Country', + 'name' => 'LU' + ], + [ + '@type' => 'Country', + 'name' => 'LV' + ], + [ + '@type' => 'Country', + 'name' => 'MA' + ], + [ + '@type' => 'Country', + 'name' => 'MC' + ], + [ + '@type' => 'Country', + 'name' => 'MD' + ], + [ + '@type' => 'Country', + 'name' => 'ME' + ], + [ + '@type' => 'Country', + 'name' => 'MG' + ], + [ + '@type' => 'Country', + 'name' => 'MH' + ], + [ + '@type' => 'Country', + 'name' => 'MK' + ], + [ + '@type' => 'Country', + 'name' => 'ML' + ], + [ + '@type' => 'Country', + 'name' => 'MN' + ], + [ + '@type' => 'Country', + 'name' => 'MO' + ], + [ + '@type' => 'Country', + 'name' => 'MR' + ], + [ + '@type' => 'Country', + 'name' => 'MT' + ], + [ + '@type' => 'Country', + 'name' => 'MU' + ], + [ + '@type' => 'Country', + 'name' => 'MV' + ], + [ + '@type' => 'Country', + 'name' => 'MW' + ], + [ + '@type' => 'Country', + 'name' => 'MX' + ], + [ + '@type' => 'Country', + 'name' => 'MY' + ], + [ + '@type' => 'Country', + 'name' => 'MZ' + ], + [ + '@type' => 'Country', + 'name' => 'NA' + ], + [ + '@type' => 'Country', + 'name' => 'NE' + ], + [ + '@type' => 'Country', + 'name' => 'NG' + ], + [ + '@type' => 'Country', + 'name' => 'NI' + ], + [ + '@type' => 'Country', + 'name' => 'NL' + ], + [ + '@type' => 'Country', + 'name' => 'NO' + ], + [ + '@type' => 'Country', + 'name' => 'NP' + ], + [ + '@type' => 'Country', + 'name' => 'NR' + ], + [ + '@type' => 'Country', + 'name' => 'NZ' + ], + [ + '@type' => 'Country', + 'name' => 'OM' + ], + [ + '@type' => 'Country', + 'name' => 'PA' + ], + [ + '@type' => 'Country', + 'name' => 'PE' + ], + [ + '@type' => 'Country', + 'name' => 'PG' + ], + [ + '@type' => 'Country', + 'name' => 'PH' + ], + [ + '@type' => 'Country', + 'name' => 'PK' + ], + [ + '@type' => 'Country', + 'name' => 'PL' + ], + [ + '@type' => 'Country', + 'name' => 'PS' + ], + [ + '@type' => 'Country', + 'name' => 'PT' + ], + [ + '@type' => 'Country', + 'name' => 'PW' + ], + [ + '@type' => 'Country', + 'name' => 'PY' + ], + [ + '@type' => 'Country', + 'name' => 'QA' + ], + [ + '@type' => 'Country', + 'name' => 'RO' + ], + [ + '@type' => 'Country', + 'name' => 'RS' + ], + [ + '@type' => 'Country', + 'name' => 'RU' + ], + [ + '@type' => 'Country', + 'name' => 'RW' + ], + [ + '@type' => 'Country', + 'name' => 'SA' + ], + [ + '@type' => 'Country', + 'name' => 'SB' + ], + [ + '@type' => 'Country', + 'name' => 'SC' + ], + [ + '@type' => 'Country', + 'name' => 'SE' + ], + [ + '@type' => 'Country', + 'name' => 'SG' + ], + [ + '@type' => 'Country', + 'name' => 'SI' + ], + [ + '@type' => 'Country', + 'name' => 'SK' + ], + [ + '@type' => 'Country', + 'name' => 'SL' + ], + [ + '@type' => 'Country', + 'name' => 'SM' + ], + [ + '@type' => 'Country', + 'name' => 'SN' + ], + [ + '@type' => 'Country', + 'name' => 'SR' + ], + [ + '@type' => 'Country', + 'name' => 'ST' + ], + [ + '@type' => 'Country', + 'name' => 'SV' + ], + [ + '@type' => 'Country', + 'name' => 'SZ' + ], + [ + '@type' => 'Country', + 'name' => 'TD' + ], + [ + '@type' => 'Country', + 'name' => 'TG' + ], + [ + '@type' => 'Country', + 'name' => 'TH' + ], + [ + '@type' => 'Country', + 'name' => 'TL' + ], + [ + '@type' => 'Country', + 'name' => 'TN' + ], + [ + '@type' => 'Country', + 'name' => 'TO' + ], + [ + '@type' => 'Country', + 'name' => 'TR' + ], + [ + '@type' => 'Country', + 'name' => 'TT' + ], + [ + '@type' => 'Country', + 'name' => 'TV' + ], + [ + '@type' => 'Country', + 'name' => 'TW' + ], + [ + '@type' => 'Country', + 'name' => 'TZ' + ], + [ + '@type' => 'Country', + 'name' => 'UA' + ], + [ + '@type' => 'Country', + 'name' => 'UG' + ], + [ + '@type' => 'Country', + 'name' => 'US' + ], + [ + '@type' => 'Country', + 'name' => 'UY' + ], + [ + '@type' => 'Country', + 'name' => 'UZ' + ], + [ + '@type' => 'Country', + 'name' => 'VC' + ], + [ + '@type' => 'Country', + 'name' => 'VN' + ], + [ + '@type' => 'Country', + 'name' => 'VU' + ], + [ + '@type' => 'Country', + 'name' => 'WS' + ], + [ + '@type' => 'Country', + 'name' => 'XK' + ], + [ + '@type' => 'Country', + 'name' => 'ZA' + ], + [ + '@type' => 'Country', + 'name' => 'ZM' + ], + [ + '@type' => 'Country', + 'name' => 'ZW' + ] + ] + ] + ] + ], + 'oEmbed' => [ + 'html' => '', + 'width' => 456, + 'height' => 380, + 'version' => '1.0', + 'provider_name' => 'Spotify', + 'provider_url' => 'https://spotify.com/', + 'type' => 'rich', + 'title' => 'A Cantar con Xabarin (Vol. I & II)', + 'thumbnail_url' => 'https://i.scdn.co/image/ab67616d00001e02022aca057f08a1d40c1f0733', + 'thumbnail_width' => 300, + 'thumbnail_height' => 300 + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.googleapis.com/', + '@type' => 'MusicAlbum', + '@id' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'url' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV', + 'name' => 'A Cantar con Xabarin (Vol. I & II)', + 'description' => 'Listen to A Cantar con Xabarin (Vol. I & II) on Spotify. Various Artists · Compilation · 1996 · 44 songs.', + 'datePublished' => '1996-03-05', + 'potentialAction' => [ + '@type' => 'ListenAction', + 'target' => [ + [ + '@type' => 'EntryPoint', + 'urlTemplate' => 'https://open.spotify.com/album/7s66wU1XJ2NsUuWM2NKiUV?autoplay=true', + 'actionPlatform' => [ + 'http://schema.org/DesktopWebPlatform', + 'http://schema.org/IOSPlatform', + 'http://schema.googleapis.com/GoogleAudioCast', + 'http://schema.googleapis.com/GoogleVideoCast' + ] + ], + 'android-app://com.spotify.music/spotify/album/7s66wU1XJ2NsUuWM2NKiUV/play' + ], + 'expectsAcceptanceOf' => [ + '@type' => 'Offer', + 'category' => 'free', + 'eligibleRegion' => [ + [ + '@type' => 'Country', + 'name' => 'AD' + ], + [ + '@type' => 'Country', + 'name' => 'AE' + ], + [ + '@type' => 'Country', + 'name' => 'AG' + ], + [ + '@type' => 'Country', + 'name' => 'AL' + ], + [ + '@type' => 'Country', + 'name' => 'AM' + ], + [ + '@type' => 'Country', + 'name' => 'AO' + ], + [ + '@type' => 'Country', + 'name' => 'AR' + ], + [ + '@type' => 'Country', + 'name' => 'AT' + ], + [ + '@type' => 'Country', + 'name' => 'AU' + ], + [ + '@type' => 'Country', + 'name' => 'AZ' + ], + [ + '@type' => 'Country', + 'name' => 'BA' + ], + [ + '@type' => 'Country', + 'name' => 'BB' + ], + [ + '@type' => 'Country', + 'name' => 'BD' + ], + [ + '@type' => 'Country', + 'name' => 'BE' + ], + [ + '@type' => 'Country', + 'name' => 'BF' + ], + [ + '@type' => 'Country', + 'name' => 'BG' + ], + [ + '@type' => 'Country', + 'name' => 'BH' + ], + [ + '@type' => 'Country', + 'name' => 'BI' + ], + [ + '@type' => 'Country', + 'name' => 'BJ' + ], + [ + '@type' => 'Country', + 'name' => 'BN' + ], + [ + '@type' => 'Country', + 'name' => 'BO' + ], + [ + '@type' => 'Country', + 'name' => 'BR' + ], + [ + '@type' => 'Country', + 'name' => 'BS' + ], + [ + '@type' => 'Country', + 'name' => 'BT' + ], + [ + '@type' => 'Country', + 'name' => 'BW' + ], + [ + '@type' => 'Country', + 'name' => 'BY' + ], + [ + '@type' => 'Country', + 'name' => 'BZ' + ], + [ + '@type' => 'Country', + 'name' => 'CA' + ], + [ + '@type' => 'Country', + 'name' => 'CH' + ], + [ + '@type' => 'Country', + 'name' => 'CI' + ], + [ + '@type' => 'Country', + 'name' => 'CL' + ], + [ + '@type' => 'Country', + 'name' => 'CM' + ], + [ + '@type' => 'Country', + 'name' => 'CO' + ], + [ + '@type' => 'Country', + 'name' => 'CR' + ], + [ + '@type' => 'Country', + 'name' => 'CV' + ], + [ + '@type' => 'Country', + 'name' => 'CW' + ], + [ + '@type' => 'Country', + 'name' => 'CY' + ], + [ + '@type' => 'Country', + 'name' => 'CZ' + ], + [ + '@type' => 'Country', + 'name' => 'DE' + ], + [ + '@type' => 'Country', + 'name' => 'DJ' + ], + [ + '@type' => 'Country', + 'name' => 'DK' + ], + [ + '@type' => 'Country', + 'name' => 'DM' + ], + [ + '@type' => 'Country', + 'name' => 'DO' + ], + [ + '@type' => 'Country', + 'name' => 'DZ' + ], + [ + '@type' => 'Country', + 'name' => 'EC' + ], + [ + '@type' => 'Country', + 'name' => 'EE' + ], + [ + '@type' => 'Country', + 'name' => 'EG' + ], + [ + '@type' => 'Country', + 'name' => 'ES' + ], + [ + '@type' => 'Country', + 'name' => 'FI' + ], + [ + '@type' => 'Country', + 'name' => 'FJ' + ], + [ + '@type' => 'Country', + 'name' => 'FM' + ], + [ + '@type' => 'Country', + 'name' => 'FR' + ], + [ + '@type' => 'Country', + 'name' => 'GA' + ], + [ + '@type' => 'Country', + 'name' => 'GB' + ], + [ + '@type' => 'Country', + 'name' => 'GD' + ], + [ + '@type' => 'Country', + 'name' => 'GE' + ], + [ + '@type' => 'Country', + 'name' => 'GH' + ], + [ + '@type' => 'Country', + 'name' => 'GM' + ], + [ + '@type' => 'Country', + 'name' => 'GN' + ], + [ + '@type' => 'Country', + 'name' => 'GQ' + ], + [ + '@type' => 'Country', + 'name' => 'GR' + ], + [ + '@type' => 'Country', + 'name' => 'GT' + ], + [ + '@type' => 'Country', + 'name' => 'GW' + ], + [ + '@type' => 'Country', + 'name' => 'GY' + ], + [ + '@type' => 'Country', + 'name' => 'HK' + ], + [ + '@type' => 'Country', + 'name' => 'HN' + ], + [ + '@type' => 'Country', + 'name' => 'HR' + ], + [ + '@type' => 'Country', + 'name' => 'HT' + ], + [ + '@type' => 'Country', + 'name' => 'HU' + ], + [ + '@type' => 'Country', + 'name' => 'ID' + ], + [ + '@type' => 'Country', + 'name' => 'IE' + ], + [ + '@type' => 'Country', + 'name' => 'IL' + ], + [ + '@type' => 'Country', + 'name' => 'IN' + ], + [ + '@type' => 'Country', + 'name' => 'IS' + ], + [ + '@type' => 'Country', + 'name' => 'IT' + ], + [ + '@type' => 'Country', + 'name' => 'JM' + ], + [ + '@type' => 'Country', + 'name' => 'JO' + ], + [ + '@type' => 'Country', + 'name' => 'JP' + ], + [ + '@type' => 'Country', + 'name' => 'KE' + ], + [ + '@type' => 'Country', + 'name' => 'KG' + ], + [ + '@type' => 'Country', + 'name' => 'KH' + ], + [ + '@type' => 'Country', + 'name' => 'KI' + ], + [ + '@type' => 'Country', + 'name' => 'KM' + ], + [ + '@type' => 'Country', + 'name' => 'KN' + ], + [ + '@type' => 'Country', + 'name' => 'KR' + ], + [ + '@type' => 'Country', + 'name' => 'KW' + ], + [ + '@type' => 'Country', + 'name' => 'KZ' + ], + [ + '@type' => 'Country', + 'name' => 'LA' + ], + [ + '@type' => 'Country', + 'name' => 'LB' + ], + [ + '@type' => 'Country', + 'name' => 'LC' + ], + [ + '@type' => 'Country', + 'name' => 'LI' + ], + [ + '@type' => 'Country', + 'name' => 'LK' + ], + [ + '@type' => 'Country', + 'name' => 'LR' + ], + [ + '@type' => 'Country', + 'name' => 'LS' + ], + [ + '@type' => 'Country', + 'name' => 'LT' + ], + [ + '@type' => 'Country', + 'name' => 'LU' + ], + [ + '@type' => 'Country', + 'name' => 'LV' + ], + [ + '@type' => 'Country', + 'name' => 'MA' + ], + [ + '@type' => 'Country', + 'name' => 'MC' + ], + [ + '@type' => 'Country', + 'name' => 'MD' + ], + [ + '@type' => 'Country', + 'name' => 'ME' + ], + [ + '@type' => 'Country', + 'name' => 'MG' + ], + [ + '@type' => 'Country', + 'name' => 'MH' + ], + [ + '@type' => 'Country', + 'name' => 'MK' + ], + [ + '@type' => 'Country', + 'name' => 'ML' + ], + [ + '@type' => 'Country', + 'name' => 'MN' + ], + [ + '@type' => 'Country', + 'name' => 'MO' + ], + [ + '@type' => 'Country', + 'name' => 'MR' + ], + [ + '@type' => 'Country', + 'name' => 'MT' + ], + [ + '@type' => 'Country', + 'name' => 'MU' + ], + [ + '@type' => 'Country', + 'name' => 'MV' + ], + [ + '@type' => 'Country', + 'name' => 'MW' + ], + [ + '@type' => 'Country', + 'name' => 'MX' + ], + [ + '@type' => 'Country', + 'name' => 'MY' + ], + [ + '@type' => 'Country', + 'name' => 'MZ' + ], + [ + '@type' => 'Country', + 'name' => 'NA' + ], + [ + '@type' => 'Country', + 'name' => 'NE' + ], + [ + '@type' => 'Country', + 'name' => 'NG' + ], + [ + '@type' => 'Country', + 'name' => 'NI' + ], + [ + '@type' => 'Country', + 'name' => 'NL' + ], + [ + '@type' => 'Country', + 'name' => 'NO' + ], + [ + '@type' => 'Country', + 'name' => 'NP' + ], + [ + '@type' => 'Country', + 'name' => 'NR' + ], + [ + '@type' => 'Country', + 'name' => 'NZ' + ], + [ + '@type' => 'Country', + 'name' => 'OM' + ], + [ + '@type' => 'Country', + 'name' => 'PA' + ], + [ + '@type' => 'Country', + 'name' => 'PE' + ], + [ + '@type' => 'Country', + 'name' => 'PG' + ], + [ + '@type' => 'Country', + 'name' => 'PH' + ], + [ + '@type' => 'Country', + 'name' => 'PK' + ], + [ + '@type' => 'Country', + 'name' => 'PL' + ], + [ + '@type' => 'Country', + 'name' => 'PS' + ], + [ + '@type' => 'Country', + 'name' => 'PT' + ], + [ + '@type' => 'Country', + 'name' => 'PW' + ], + [ + '@type' => 'Country', + 'name' => 'PY' + ], + [ + '@type' => 'Country', + 'name' => 'QA' + ], + [ + '@type' => 'Country', + 'name' => 'RO' + ], + [ + '@type' => 'Country', + 'name' => 'RS' + ], + [ + '@type' => 'Country', + 'name' => 'RU' + ], + [ + '@type' => 'Country', + 'name' => 'RW' + ], + [ + '@type' => 'Country', + 'name' => 'SA' + ], + [ + '@type' => 'Country', + 'name' => 'SB' + ], + [ + '@type' => 'Country', + 'name' => 'SC' + ], + [ + '@type' => 'Country', + 'name' => 'SE' + ], + [ + '@type' => 'Country', + 'name' => 'SG' + ], + [ + '@type' => 'Country', + 'name' => 'SI' + ], + [ + '@type' => 'Country', + 'name' => 'SK' + ], + [ + '@type' => 'Country', + 'name' => 'SL' + ], + [ + '@type' => 'Country', + 'name' => 'SM' + ], + [ + '@type' => 'Country', + 'name' => 'SN' + ], + [ + '@type' => 'Country', + 'name' => 'SR' + ], + [ + '@type' => 'Country', + 'name' => 'ST' + ], + [ + '@type' => 'Country', + 'name' => 'SV' + ], + [ + '@type' => 'Country', + 'name' => 'SZ' + ], + [ + '@type' => 'Country', + 'name' => 'TD' + ], + [ + '@type' => 'Country', + 'name' => 'TG' + ], + [ + '@type' => 'Country', + 'name' => 'TH' + ], + [ + '@type' => 'Country', + 'name' => 'TL' + ], + [ + '@type' => 'Country', + 'name' => 'TN' + ], + [ + '@type' => 'Country', + 'name' => 'TO' + ], + [ + '@type' => 'Country', + 'name' => 'TR' + ], + [ + '@type' => 'Country', + 'name' => 'TT' + ], + [ + '@type' => 'Country', + 'name' => 'TV' + ], + [ + '@type' => 'Country', + 'name' => 'TW' + ], + [ + '@type' => 'Country', + 'name' => 'TZ' + ], + [ + '@type' => 'Country', + 'name' => 'UA' + ], + [ + '@type' => 'Country', + 'name' => 'UG' + ], + [ + '@type' => 'Country', + 'name' => 'US' + ], + [ + '@type' => 'Country', + 'name' => 'UY' + ], + [ + '@type' => 'Country', + 'name' => 'UZ' + ], + [ + '@type' => 'Country', + 'name' => 'VC' + ], + [ + '@type' => 'Country', + 'name' => 'VN' + ], + [ + '@type' => 'Country', + 'name' => 'VU' + ], + [ + '@type' => 'Country', + 'name' => 'WS' + ], + [ + '@type' => 'Country', + 'name' => 'XK' + ], + [ + '@type' => 'Country', + 'name' => 'ZA' + ], + [ + '@type' => 'Country', + 'name' => 'ZM' + ], + [ + '@type' => 'Country', + 'name' => 'ZW' + ] + ] + ] + ] + ] + ] +]; diff --git a/tests/fixtures/polldaddy.com.poll-7012505.php b/tests/fixtures/polldaddy.com.poll-7012505.php new file mode 100644 index 00000000..b2494f4d --- /dev/null +++ b/tests/fixtures/polldaddy.com.poll-7012505.php @@ -0,0 +1,29 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Poll Answers: Option #1, Option #2,', + 'favicon' => 'https://app.crowdsignal.com/images/favicon.png', + 'feeds' => [ + 'https://poll.fm/7012505/feed' + ], + 'icon' => null, + 'image' => 'https://app.crowdsignal.com/images/twitter-card.png', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Poll', + 'providerUrl' => 'https://poll.fm/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Which design do you prefer?', + 'url' => 'https://poll.fm/7012505', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/sassmeister.com.gist-1122e441f0434ec6eb2a.php b/tests/fixtures/sassmeister.com.gist-1122e441f0434ec6eb2a.php new file mode 100644 index 00000000..88059153 --- /dev/null +++ b/tests/fixtures/sassmeister.com.gist-1122e441f0434ec6eb2a.php @@ -0,0 +1,32 @@ + 'Jed Foster and Dale Sande', + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '

Play with this gist on SassMeister.

', + 'width' => null, + 'height' => 480, + 'ratio' => null + ], + 'description' => 'SassMeister is a playground for Sass. Add some Sass and SassMeister will show you the rendered CSS.', + 'favicon' => 'https://www.sassmeister.com/favicon.ico', + 'feeds' => [], + 'icon' => 'https://www.sassmeister.com/logo192.png', + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Sassmeister', + 'providerUrl' => 'https://www.sassmeister.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'SassMeister | The Sass Playground!', + 'url' => 'https://www.sassmeister.com/gist/1122e441f0434ec6eb2a', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/slides.com.alexwalker-responsive-svg.php b/tests/fixtures/slides.com.alexwalker-responsive-svg.php new file mode 100644 index 00000000..07d934b4 --- /dev/null +++ b/tests/fixtures/slides.com.alexwalker-responsive-svg.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 576, + 'height' => 420, + 'ratio' => 72.917 + ], + 'description' => 'A presentation created with Slides.', + 'favicon' => 'https://slides.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://media.slid.es/thumbnails/alexwalker/0b188c/responsive-svg.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Slides', + 'providerUrl' => 'https://slides.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'responsive-svg', + 'url' => 'https://slides.com/alexwalker/responsive-svg/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/snipplr.com.view-72914-better-html-5-basic-starter-template.php b/tests/fixtures/snipplr.com.view-72914-better-html-5-basic-starter-template.php new file mode 100644 index 00000000..73f09439 --- /dev/null +++ b/tests/fixtures/snipplr.com.view-72914-better-html-5-basic-starter-template.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://snipplr.com/favicon.ico?v3', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Snipplr', + 'providerUrl' => 'https://snipplr.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Snipplr - Login', + 'url' => 'https://snipplr.com/login/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/soundcloud.com.bruceneilmusic.php b/tests/fixtures/soundcloud.com.bruceneilmusic.php new file mode 100644 index 00000000..5d635f55 --- /dev/null +++ b/tests/fixtures/soundcloud.com.bruceneilmusic.php @@ -0,0 +1,54 @@ + 'Bruce Neil', + 'authorUrl' => 'https://soundcloud.com/bruceneilmusic', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => 450, + 'ratio' => null + ], + 'description' => 'Bruce Neil from Wokingham is a singer/songwriter with a folk inspired sound, producing songs with heartfelt depth and lyrics that captivate the listener, taking them on an insightful and thought-provoking journey. As a winner of BBC Introducing, resulting in air play nationally, he has recently achieved widespread public attention following the video release of his percussive folk rendition of Guns N’ Roses track Paradise City. Not only did this go viral on social media, it was endorsed by the band themselves and has achieved recognition and air play from several US radio stations. He takes his musical inspiration and guitar-playing style from the likes of Passenger and Mick Flannery.', + 'favicon' => 'https://a-v2.sndcdn.com/assets/images/sc-icons/favicon-2cadd14bdb.ico', + 'feeds' => [], + 'icon' => 'https://a-v2.sndcdn.com/assets/images/sc-icons/ios-a62dfc8fe7.png', + 'image' => 'https://i1.sndcdn.com/avatars-000137863509-h9h7dr-t500x500.jpg', + 'keywords' => [ + 'record', + 'sounds', + 'share', + 'sound', + 'audio', + 'tracks', + 'music', + 'soundcloud' + ], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'SoundCloud', + 'providerUrl' => 'https://soundcloud.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Bruce Neil', + 'url' => 'https://soundcloud.com/bruceneilmusic', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => 1.0, + 'type' => 'rich', + 'provider_name' => 'SoundCloud', + 'provider_url' => 'https://soundcloud.com/', + 'height' => 450, + 'width' => '100%', + 'title' => 'Bruce Neil', + 'description' => 'Bruce Neil from Wokingham is a singer/songwriter with a folk inspired sound, producing songs with heartfelt depth and lyrics that captivate the listener, taking them on an insightful and thought-provoking journey. As a winner of BBC Introducing, resulting in air play nationally, he has recently achieved widespread public attention following the video release of his percussive folk rendition of Guns N’ Roses track Paradise City. Not only did this go viral on social media, it was endorsed by the band themselves and has achieved recognition and air play from several US radio stations. He takes his musical inspiration and guitar-playing style from the likes of Passenger and Mick Flannery.', + 'thumbnail_url' => 'https://i1.sndcdn.com/avatars-000137863509-h9h7dr-t500x500.jpg', + 'html' => '', + 'author_name' => 'Bruce Neil', + 'author_url' => 'https://soundcloud.com/bruceneilmusic' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/soundcloud.com.ididthat-1-lowe-ct-cape-times-world-cup.php b/tests/fixtures/soundcloud.com.ididthat-1-lowe-ct-cape-times-world-cup.php new file mode 100644 index 00000000..1b284744 --- /dev/null +++ b/tests/fixtures/soundcloud.com.ididthat-1-lowe-ct-cape-times-world-cup.php @@ -0,0 +1,54 @@ + 'IDIDTHAT.co', + 'authorUrl' => 'https://soundcloud.com/ididthat-1', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => 400, + 'ratio' => null + ], + 'description' => 'IDIDTHAT.co Promotes and Connects South Africa’s Advertising and Production Industry.', + 'favicon' => 'https://a-v2.sndcdn.com/assets/images/sc-icons/favicon-2cadd14bdb.ico', + 'feeds' => [], + 'icon' => 'https://a-v2.sndcdn.com/assets/images/sc-icons/ios-a62dfc8fe7.png', + 'image' => 'https://soundcloud.com/images/fb_placeholder.png', + 'keywords' => [ + 'record', + 'sounds', + 'share', + 'sound', + 'audio', + 'tracks', + 'music', + 'soundcloud' + ], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'SoundCloud', + 'providerUrl' => 'https://soundcloud.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'LOWE CT Cape Times - World Cup by IDIDTHAT.co', + 'url' => 'https://soundcloud.com/ididthat-1/lowe-ct-cape-times-world-cup', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => 1.0, + 'type' => 'rich', + 'provider_name' => 'SoundCloud', + 'provider_url' => 'https://soundcloud.com/', + 'height' => 400, + 'width' => '100%', + 'title' => 'LOWE CT Cape Times - World Cup by IDIDTHAT.co', + 'description' => '', + 'thumbnail_url' => 'https://soundcloud.com/images/fb_placeholder.png', + 'html' => '', + 'author_name' => 'IDIDTHAT.co', + 'author_url' => 'https://soundcloud.com/ididthat-1' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/soundcloud.com.zedsdead-zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy.php b/tests/fixtures/soundcloud.com.zedsdead-zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy.php new file mode 100644 index 00000000..ebf911d5 --- /dev/null +++ b/tests/fixtures/soundcloud.com.zedsdead-zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy.php @@ -0,0 +1,66 @@ + 'Zeds Dead', + 'authorUrl' => 'https://soundcloud.com/zedsdead', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => 400, + 'ratio' => null + ], + 'description' => 'MUSIC VIDEO : https://www.youtube.com/watch?v=VJm7IPrBmLY Zeds Dead www.facebook.com/zedsdead www.twitter.com/whoszed www.instagram.com/zedsdeadofficial Twin Shadow www.facebook.com/twnshdw www.twitter.com/twinshadow www.instagram.com/thetwinshadow', + 'favicon' => 'https://a-v2.sndcdn.com/assets/images/sc-icons/favicon-2cadd14bdb.ico', + 'feeds' => [], + 'icon' => 'https://a-v2.sndcdn.com/assets/images/sc-icons/ios-a62dfc8fe7.png', + 'image' => 'https://i1.sndcdn.com/artworks-fdcKTkNSeA5J-0-t500x500.jpg', + 'keywords' => [ + 'record', + 'sounds', + 'share', + 'sound', + 'audio', + 'tracks', + 'music', + 'soundcloud' + ], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'SoundCloud', + 'providerUrl' => 'https://soundcloud.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Zeds Dead feat. Twin Shadow & D\'Angelo Lacy - Lost You by Zeds Dead', + 'url' => 'https://soundcloud.com/zedsdead/zeds-dead-twin-shadow-lost-you-feat-dangelo-lacy', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => 1.0, + 'type' => 'rich', + 'provider_name' => 'SoundCloud', + 'provider_url' => 'https://soundcloud.com/', + 'height' => 400, + 'width' => '100%', + 'title' => 'Zeds Dead feat. Twin Shadow & D\'Angelo Lacy - Lost You by Zeds Dead', + 'description' => 'MUSIC VIDEO : https://www.youtube.com/watch?v=VJm7IPrBmLY + +Zeds Dead +www.facebook.com/zedsdead +www.twitter.com/whoszed +www.instagram.com/zedsdeadofficial + +Twin Shadow +www.facebook.com/twnshdw +www.twitter.com/twinshadow +www.instagram.com/thetwinshadow + +', + 'thumbnail_url' => 'https://i1.sndcdn.com/artworks-fdcKTkNSeA5J-0-t500x500.jpg', + 'html' => '', + 'author_name' => 'Zeds Dead', + 'author_url' => 'https://soundcloud.com/zedsdead' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/twitter.com.pepephone-status-436461658601713664.php b/tests/fixtures/twitter.com.pepephone-status-436461658601713664.php new file mode 100644 index 00000000..2b5b0fcb --- /dev/null +++ b/tests/fixtures/twitter.com.pepephone-status-436461658601713664.php @@ -0,0 +1,48 @@ + 'Pepephone', + 'authorUrl' => 'https://twitter.com/pepephone', + 'cms' => null, + 'code' => [ + 'html' => ' ', + 'width' => 550, + 'height' => null, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'https://abs.twimg.com/favicons/twitter-pip.3.ico', + 'feeds' => [], + 'icon' => 'https://abs.twimg.com/responsive-web/client-web/icon-ios.77d25eba.png', + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Twitter', + 'providerUrl' => 'https://twitter.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'x.com', + 'url' => 'https://twitter.com/pepephone/status/436461658601713664', + 'linkedData' => [], + 'oEmbed' => [ + 'url' => 'https://twitter.com/pepephone/status/436461658601713664', + 'author_name' => 'Pepephone', + 'author_url' => 'https://twitter.com/pepephone', + 'html' => ' + + +', + 'width' => 550, + 'height' => null, + 'type' => 'rich', + 'cache_age' => '3153600000', + 'provider_name' => 'Twitter', + 'provider_url' => 'https://twitter.com/', + 'version' => '1.0' + ], + 'api' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/vimeo.com.235352744.php b/tests/fixtures/vimeo.com.235352744.php new file mode 100644 index 00000000..4a18fb15 --- /dev/null +++ b/tests/fixtures/vimeo.com.235352744.php @@ -0,0 +1,42 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 640, + 'height' => 360, + 'ratio' => 56.25 + ], + 'description' => 'Sorry, we couldn’t find that page', + 'favicon' => 'https://f.vimeocdn.com/images_v6/favicon.ico?75abfbb122dbdc379bb1a024f2874f879d5a01a1', + 'feeds' => [], + 'icon' => 'https://i.vimeocdn.com/favicon/main-touch_180', + 'image' => null, + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Vimeo', + 'providerUrl' => 'https://vimeo.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'VimeUhOh', + 'url' => 'https://vimeo.com/235352744', + 'linkedData' => [], + 'oEmbed' => [ + 'type' => 'video', + 'version' => '1.0', + 'provider_name' => 'Vimeo', + 'provider_url' => 'https://vimeo.com/', + 'html' => '', + 'width' => 640, + 'height' => 360, + 'video_id' => 235352744, + 'uri' => '/videos/235352744:ebd66989cc' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/wordpress.tv.2013-09-06-dave-ross-optimize-image-files-like-a-pro.php b/tests/fixtures/wordpress.tv.2013-09-06-dave-ross-optimize-image-files-like-a-pro.php new file mode 100644 index 00000000..92ebfb7c --- /dev/null +++ b/tests/fixtures/wordpress.tv.2013-09-06-dave-ross-optimize-image-files-like-a-pro.php @@ -0,0 +1,113 @@ + 'WordPress.tv', + 'authorUrl' => 'https://wordpress.tv/author/anonvideoupload/', + 'cms' => 'wordpress', + 'code' => [ + 'html' => '
Dave Ross: Optimize Image Files Like a Pro
', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => 'Images, even small ones, can be the biggest files that make up your site. Learn the tools, plugins, and theming techniques you’ll want to start using to shrink your page load times and save your mo…', + 'favicon' => 'https://s0.wp.com/i/favicon.ico', + 'feeds' => [ + 'https://wordpress.tv/feed/' + ], + 'icon' => 'https://s0.wp.com/i/webclip.png', + 'image' => 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_scruberthumbnail_0.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'WordPress.tv', + 'providerUrl' => 'http://wordpress.tv/', + 'publishedTime' => '2013-09-06 10:43:21', + 'redirect' => null, + 'title' => 'Dave Ross: Optimize Image Files Like a Pro', + 'url' => 'https://wordpress.tv/2013/09/06/dave-ross-optimize-image-files-like-a-pro/', + 'linkedData' => [ + '@context' => 'https://schema.org/', + '@graph' => [ + [ + '@type' => 'VideoObject', + 'actor' => [ + [ + '@type' => 'Person', + 'name' => 'Dave Ross', + 'url' => 'https://wordpress.tv/speakers/dave-ross/' + ] + ], + 'name' => 'Dave Ross: Optimize Image Files Like a Pro', + 'url' => 'https://wordpress.tv/2013/09/06/dave-ross-optimize-image-files-like-a-pro/', + 'contentUrl' => [ + 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_hd.mp4', + 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_dvd.mp4', + 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_std.mp4' + ], + 'description' => 'Images, even small ones, can be the biggest files that make up your site. Learn the tools, plugins, and theming techniques you’ll want to start using to shrink your page load times and save your mobile users a few bucks without sacrificing image quality. + +Presentation Slides »', + 'duration' => 'P0DT00H29M20S', + 'height' => '1080', + 'inLanguage' => 'en', + 'isFamilyFriendly' => true, + 'thumbnailUrl' => 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_scruberthumbnail_0.jpg', + 'uploadDate' => '2013-09-06', + 'width' => '1920' + ] + ] + ], + 'oEmbed' => [ + 'version' => '1.0', + 'provider_name' => 'WordPress.tv', + 'provider_url' => 'http://wordpress.tv/', + 'author_name' => 'WordPress.tv', + 'author_url' => 'https://wordpress.tv/author/anonvideoupload/', + 'title' => 'Dave Ross: Optimize Image Files Like a Pro', + 'html' => '
Dave Ross: Optimize Image Files Like a Pro
+', + 'type' => 'rich' + ], + 'allLinkedData' => [ + [ + '@context' => 'https://schema.org/', + '@graph' => [ + [ + '@type' => 'VideoObject', + 'actor' => [ + [ + '@type' => 'Person', + 'name' => 'Dave Ross', + 'url' => 'https://wordpress.tv/speakers/dave-ross/' + ] + ], + 'name' => 'Dave Ross: Optimize Image Files Like a Pro', + 'url' => 'https://wordpress.tv/2013/09/06/dave-ross-optimize-image-files-like-a-pro/', + 'contentUrl' => [ + 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_hd.mp4', + 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_dvd.mp4', + 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_std.mp4' + ], + 'description' => 'Images, even small ones, can be the biggest files that make up your site. Learn the tools, plugins, and theming techniques you’ll want to start using to shrink your page load times and save your mobile users a few bucks without sacrificing image quality. + +Presentation Slides »', + 'duration' => 'P0DT00H29M20S', + 'height' => '1080', + 'inLanguage' => 'en', + 'isFamilyFriendly' => true, + 'thumbnailUrl' => 'https://videos.files.wordpress.com/TqDCJmoq/optimize-image-files_scruberthumbnail_0.jpg', + 'uploadDate' => '2013-09-06', + 'width' => '1920' + ] + ] + ] + ] +]; diff --git a/tests/fixtures/www.23hq.com.zzleeper-photo-16600737.php b/tests/fixtures/www.23hq.com.zzleeper-photo-16600737.php new file mode 100644 index 00000000..04207dcb --- /dev/null +++ b/tests/fixtures/www.23hq.com.zzleeper-photo-16600737.php @@ -0,0 +1,68 @@ + 'Zzleeper', + 'authorUrl' => 'https://www.23hq.com/Zzleeper/', + 'cms' => null, + 'code' => null, + 'description' => 'På god väns inrådan kommer det även bultförband vid pilarna. Låter bra tycker jag. (Better safe than sorry)', + 'favicon' => 'https://www.23hq.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg', + 'keywords' => [ + 'compartir fotos', + 'compartirfotos', + '23', + 'foto digital', + 'galeria de fotos', + 'álbum de fotos', + 'comparte foto', + 'almacenamiento de fotos', + 'almacenamiento de imágenes', + 'picture storage', + 'álbum de fotos online', + 'picture gallery', + 'galería de imágenes', + 'impresiones de fotos', + 'compartir imágenes', + 'cámara digital', + 'organizar fotos', + 'telefono con cámara', + 'moblog', + 'mblog', + 'photoblog', + 'tags', + 'busqueda de fotos', + 'veintitres', + 'chassi framvagn' + ], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => '23', + 'providerUrl' => 'http://www.23hq.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'På god väns inrådan kommer det även bultförband vid pilarna. Låter bra tycker jag. (Better safe than sorry)', + 'url' => 'https://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'photo', + 'title' => 'På god väns inrådan kommer det även bultförband vid pilarna. Låter bra tycker jag. (Better safe than sorry)', + 'author_name' => 'Zzleeper', + 'author_url' => 'https://www.23hq.com/Zzleeper/', + 'cache_age' => 3600, + 'provider_name' => 23, + 'provider_url' => 'http://www.23hq.com/', + 'width' => 756, + 'height' => 567, + 'url' => 'https://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg', + 'thumbnail_width' => 756, + 'thumbnail_height' => 567, + 'thumbnail_url' => 'https://www.23hq.com/16171062/16600737_ac392e8a4d667e4726fbafc8a21728d5_large.jpg' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.abanca.com.gl.php b/tests/fixtures/www.abanca.com.gl.php new file mode 100644 index 00000000..c3ccca8d --- /dev/null +++ b/tests/fixtures/www.abanca.com.gl.php @@ -0,0 +1,70 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'ABANCA, a banca para particulares e negocios. Conta online, conta nómina, conta joven, hipotecas, depósitos, fondos, seguros e moito máis. Banco ABANCA.', + 'favicon' => 'https://www.abanca.com/favicon.png', + 'feeds' => [], + 'icon' => 'https://www.abanca.com/apple-touch-icon-152x152-precomposed.png', + 'image' => 'https://www.abanca.com/img/logo-social.jpg', + 'keywords' => [ + 'abanca', + 'abanca particulares', + 'abanca empresas', + 'abanca autónomos', + 'servizos bancarios', + 'servizos financeios', + 'produtos financeiros', + 'produtos bancarios' + ], + 'language' => 'gl', + 'languages' => [ + 'gl' => 'https://www.abanca.com/gl/', + 'es' => 'https://www.abanca.com/es/', + 'eu' => 'https://www.abanca.com/eu/' + ], + 'license' => null, + 'providerName' => 'Abanca', + 'providerUrl' => 'https://www.abanca.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'ABANCA banca online para particulares e empresas | ABANCA', + 'url' => 'https://www.abanca.com/gl/', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'Organization', + 'name' => '', + 'url' => '//www.abanca.com', + 'logo' => '//www.abanca.com/img/logo-social.jpg', + 'sameAs' => [], + 'contactPoint' => [ + [ + '@type' => 'ContactPoint', + 'telephone' => '-', + 'contactType' => 'customer service' + ] + ] + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'Organization', + 'name' => '', + 'url' => '//www.abanca.com', + 'logo' => '//www.abanca.com/img/logo-social.jpg', + 'sameAs' => [], + 'contactPoint' => [ + [ + '@type' => 'ContactPoint', + 'telephone' => '-', + 'contactType' => 'customer service' + ] + ] + ] + ] +]; diff --git a/tests/fixtures/www.aol.com.video-view-pile-of-recovering-foster-kittens-is-purrfect-595fe75985eb42109b69bedb.php b/tests/fixtures/www.aol.com.video-view-pile-of-recovering-foster-kittens-is-purrfect-595fe75985eb42109b69bedb.php new file mode 100644 index 00000000..2f4eaffe --- /dev/null +++ b/tests/fixtures/www.aol.com.video-view-pile-of-recovering-foster-kittens-is-purrfect-595fe75985eb42109b69bedb.php @@ -0,0 +1,27 @@ + 'AOL', + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'The AOL.com video experience serves up the best video content from AOL and around the web, curating informative and entertaining snackable videos.', + 'favicon' => 'https://s.yimg.com/cv/apiv2/aolfp/images/favicon/favicon-16x16.png', + 'feeds' => [], + 'icon' => 'https://s.yimg.com/cv/apiv2/aolfp/images/favicon/apple-touch-icon-57x57.png', + 'image' => 'https://s.yimg.com/cv/apiv2/aolfp/metadata/og-image.png', + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => null, + 'providerName' => 'AOL.com', + 'providerUrl' => 'https://www.aol.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'AOL Video - Serving the best video content from AOL and around the web', + 'url' => 'https://www.aol.com/video/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.bbc.co.uk.news-uk-54222286.php b/tests/fixtures/www.bbc.co.uk.news-uk-54222286.php new file mode 100644 index 00000000..05a9cead --- /dev/null +++ b/tests/fixtures/www.bbc.co.uk.news-uk-54222286.php @@ -0,0 +1,101 @@ + 'https://www.facebook.com/bbcnews', + 'authorUrl' => 'https://twitter.com/BBCNews', + 'cms' => null, + 'code' => null, + 'description' => 'Five things you need to know about the coronavirus pandemic this Sunday morning.', + 'favicon' => 'https://www.bbc.co.uk/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://ichef.bbci.co.uk/news/1024/branded_news/CC94/production/_111527325_index_daily_update_version02_cv_976new.png', + 'keywords' => [], + 'language' => 'en-GB', + 'languages' => [ + 'x-default' => 'https://www.bbc.com/news/uk-54222286', + 'en-gb' => 'https://www.bbc.co.uk/news/uk-54222286', + 'en' => 'https://www.bbc.com/news/uk-54222286' + ], + 'license' => null, + 'providerName' => 'BBC News', + 'providerUrl' => 'https://www.bbc.co.uk/', + 'publishedTime' => '2020-09-20 06:33:33', + 'redirect' => null, + 'title' => 'Coronavirus: £10,000 fines for failing to self-isolate and lockdown life in photos', + 'url' => 'https://www.bbc.co.uk/news/uk-54222286', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'ReportageNewsArticle', + 'url' => 'https://www.bbc.co.uk/news/uk-54222286', + 'publisher' => [ + '@type' => 'NewsMediaOrganization', + 'name' => 'BBC News', + 'publishingPrinciples' => 'http://www.bbc.co.uk/news/help-41670342', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://static.files.bbci.co.uk/ws/simorgh-assets/public/news/images/metadata/poster-1024x576.png' + ] + ], + 'datePublished' => '2020-09-20T06:33:33.000Z', + 'dateModified' => '2020-09-20T06:33:33.000Z', + 'description' => 'Five things you need to know about the coronavirus pandemic this Sunday morning.', + 'headline' => 'Coronavirus: £10,000 fines for failing to self-isolate and lockdown life in photos', + 'image' => [ + '@type' => 'ImageObject', + 'width' => 1024, + 'height' => 576, + 'url' => 'https://ichef.bbci.co.uk/news/1024/branded_news/CC94/production/_111527325_index_daily_update_version02_cv_976new.png' + ], + 'thumbnailUrl' => 'https://ichef.bbci.co.uk/news/1024/branded_news/CC94/production/_111527325_index_daily_update_version02_cv_976new.png', + 'mainEntityOfPage' => 'https://www.bbc.co.uk/news/uk-54222286', + 'author' => [ + '@type' => 'NewsMediaOrganization', + 'name' => 'BBC News', + 'noBylinesPolicy' => 'http://www.bbc.co.uk/news/help-41670342#authorexpertise', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://static.files.bbci.co.uk/ws/simorgh-assets/public/news/images/metadata/poster-1024x576.png' + ] + ] + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'ReportageNewsArticle', + 'url' => 'https://www.bbc.co.uk/news/uk-54222286', + 'publisher' => [ + '@type' => 'NewsMediaOrganization', + 'name' => 'BBC News', + 'publishingPrinciples' => 'http://www.bbc.co.uk/news/help-41670342', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://static.files.bbci.co.uk/ws/simorgh-assets/public/news/images/metadata/poster-1024x576.png' + ] + ], + 'datePublished' => '2020-09-20T06:33:33.000Z', + 'dateModified' => '2020-09-20T06:33:33.000Z', + 'description' => 'Five things you need to know about the coronavirus pandemic this Sunday morning.', + 'headline' => 'Coronavirus: £10,000 fines for failing to self-isolate and lockdown life in photos', + 'image' => [ + '@type' => 'ImageObject', + 'width' => 1024, + 'height' => 576, + 'url' => 'https://ichef.bbci.co.uk/news/1024/branded_news/CC94/production/_111527325_index_daily_update_version02_cv_976new.png' + ], + 'thumbnailUrl' => 'https://ichef.bbci.co.uk/news/1024/branded_news/CC94/production/_111527325_index_daily_update_version02_cv_976new.png', + 'mainEntityOfPage' => 'https://www.bbc.co.uk/news/uk-54222286', + 'author' => [ + '@type' => 'NewsMediaOrganization', + 'name' => 'BBC News', + 'noBylinesPolicy' => 'http://www.bbc.co.uk/news/help-41670342#authorexpertise', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://static.files.bbci.co.uk/ws/simorgh-assets/public/news/images/metadata/poster-1024x576.png' + ] + ] + ] + ] +]; diff --git a/tests/fixtures/www.dailymotion.com.video-xy0wd.php b/tests/fixtures/www.dailymotion.com.video-xy0wd.php new file mode 100644 index 00000000..d73472df --- /dev/null +++ b/tests/fixtures/www.dailymotion.com.video-xy0wd.php @@ -0,0 +1,47 @@ + 'jeanbamin', + 'authorUrl' => 'https://www.dailymotion.com/jeanbamin', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 480, + 'height' => 360, + 'ratio' => 75.0 + ], + 'description' => 'Regardez Chats paresseux - jeanbamin sur Dailymotion', + 'favicon' => 'https://static1.dmcdn.net/neon/prod/favicons/android-icon-36x36.ddad17021e43a6fe3840bd2d31067714.png', + 'feeds' => [], + 'icon' => 'https://static1.dmcdn.net/neon/prod/favicons/apple-icon-precomposed.a966d521999d793bdfcbe436bb56dad4.png', + 'image' => 'https://s2.dmcdn.net/v/63aD1au2tjDf9rTG/x240', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Dailymotion', + 'providerUrl' => 'https://www.dailymotion.com/', + 'publishedTime' => '2007-01-08 11:41:29', + 'redirect' => null, + 'title' => 'Chats paresseux', + 'url' => 'https://www.dailymotion.com/video/xy0wd', + 'linkedData' => [], + 'oEmbed' => [ + 'type' => 'video', + 'version' => '1.0', + 'provider_name' => 'Dailymotion', + 'provider_url' => 'https://www.dailymotion.com/', + 'title' => 'Chats paresseux', + 'description' => '', + 'author_name' => 'jeanbamin', + 'author_url' => 'https://www.dailymotion.com/jeanbamin', + 'width' => 480, + 'height' => 360, + 'html' => '', + 'thumbnail_url' => 'https://s2.dmcdn.net/v/63aD1au2tjDf9rTG/x240', + 'thumbnail_width' => 320, + 'thumbnail_height' => 240 + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.deviantart.com.art-misty-510056679.php b/tests/fixtures/www.deviantart.com.art-misty-510056679.php new file mode 100644 index 00000000..040b3629 --- /dev/null +++ b/tests/fixtures/www.deviantart.com.art-misty-510056679.php @@ -0,0 +1,66 @@ + 'sakimichan', + 'authorUrl' => 'https://www.deviantart.com/sakimichan', + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://st.deviantart.net/eclipse/icons/da_favicon_v2.ico', + 'feeds' => [], + 'icon' => 'https://st.deviantart.net/eclipse/icons/ios-180.png', + 'image' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg/v1/fit/w_300,h_900,q_70,strp/misty_by_sakimichan_d8foa93-300w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'DeviantArt', + 'providerUrl' => 'https://www.deviantart.com/', + 'publishedTime' => '2015-01-27 16:55:07', + 'redirect' => null, + 'title' => 'Misty', + 'url' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzlhZDhmYmM4LWFlZTgtNGU5Mi1hMDRiLTZhYmY3YTAzNmE1MVwvZDhmb2E5My04ZTFmYWRlOS0xODUzLTQ2NDQtYWY4Mi0yZWMyMTU5MGJmOTQuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0._JiXuDZWqsoAgateXxPBaC3_EPfHdri7pJCeKFhXnjA', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'photo', + 'title' => 'Misty', + 'category' => 'Fan Art > Digital Art > Drawings > Games', + 'url' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzlhZDhmYmM4LWFlZTgtNGU5Mi1hMDRiLTZhYmY3YTAzNmE1MVwvZDhmb2E5My04ZTFmYWRlOS0xODUzLTQ2NDQtYWY4Mi0yZWMyMTU5MGJmOTQuanBnIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0._JiXuDZWqsoAgateXxPBaC3_EPfHdri7pJCeKFhXnjA', + 'author_name' => 'sakimichan', + 'author_url' => 'https://www.deviantart.com/sakimichan', + 'provider_name' => 'DeviantArt', + 'provider_url' => 'https://www.deviantart.com/', + 'safety' => 'nonadult', + 'pubdate' => '2015-01-27T16:55:07-08:00', + 'community' => [ + 'statistics' => [ + '_attributes' => [ + 'views' => 386632, + 'favorites' => 22702, + 'comments' => 675, + 'downloads' => 0 + ] + ] + ], + 'copyright' => [ + '_attributes' => [ + 'url' => 'https://www.deviantart.com/sakimichan', + 'year' => '2015', + 'entity' => 'sakimichan' + ] + ], + 'width' => '695', + 'height' => '900', + 'imagetype' => 'jpg', + 'thumbnail_url' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg/v1/fit/w_300,h_900,q_70,strp/misty_by_sakimichan_d8foa93-300w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM', + 'thumbnail_width' => 300, + 'thumbnail_height' => 388, + 'thumbnail_url_150' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg/v1/fit/w_150,h_150,q_70,strp/misty_by_sakimichan_d8foa93-150.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM', + 'thumbnail_url_200h' => 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/9ad8fbc8-aee8-4e92-a04b-6abf7a036a51/d8foa93-8e1fade9-1853-4644-af82-2ec21590bf94.jpg/v1/crop/w_154,h_200,x_0,y_0,scl_0.22302158273381,q_70,strp/misty_by_sakimichan_d8foa93-200h.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9OTAwIiwicGF0aCI6IlwvZlwvOWFkOGZiYzgtYWVlOC00ZTkyLWEwNGItNmFiZjdhMDM2YTUxXC9kOGZvYTkzLThlMWZhZGU5LTE4NTMtNDY0NC1hZjgyLTJlYzIxNTkwYmY5NC5qcGciLCJ3aWR0aCI6Ijw9Njk1In1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmltYWdlLm9wZXJhdGlvbnMiXX0.ms0Mi2WrZ6RA_clNOJNYh5k9Ow2CkK06A_NmVeMS4hM', + 'thumbnail_width_200h' => 154, + 'thumbnail_height_200h' => 200 + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.flickr.com.photos-desescribir-sets-72157650686499888.php b/tests/fixtures/www.flickr.com.photos-desescribir-sets-72157650686499888.php new file mode 100644 index 00000000..d3630938 --- /dev/null +++ b/tests/fixtures/www.flickr.com.photos-desescribir-sets-72157650686499888.php @@ -0,0 +1,145 @@ + 'desescribir', + 'authorUrl' => 'https://www.flickr.com/photos/desescribir/', + 'cms' => null, + 'code' => [ + 'html' => '\'Günther', + 'width' => 800, + 'height' => 600, + 'ratio' => 75.0 + ], + 'description' => 'Explore this photo album by desescribir on Flickr!', + 'favicon' => 'https://combo.staticflickr.com/pw/favicon.ico', + 'feeds' => [ + 'https://www.flickr.com/services/feeds/photoset.gne?nsid=34912442@N03&set=72157650686499888&lang=en-us&format=atom' + ], + 'icon' => 'https://combo.staticflickr.com/pw/images/favicons/favicon-120.png', + 'image' => 'https://live.staticflickr.com/8572/16055522574_ce77fde14e_b.jpg', + 'keywords' => [], + 'language' => 'en-us', + 'languages' => [], + 'license' => 'https://creativecommons.org/licenses/by-nc-nd/2.0/', + 'providerName' => 'Flickr', + 'providerUrl' => 'https://www.flickr.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Günther Förg. Verfolgen Malerei / Fundación Luís Seoane', + 'url' => 'https://www.flickr.com/photos/desescribir/sets/72157650686499888', + 'linkedData' => [ + '@context' => 'https://schema.org/', + '@type' => 'BlogPosting', + 'mainEntityOfPage' => [ + '@type' => 'WebPage', + '@id' => 'https://www.flickr.com/photos/desescribir/sets/72157650686499888' + ], + 'headline' => 'Günther Förg. Verfolgen Malerei / Fundación Luís Seoane', + 'image' => [ + '@type' => 'ImageObject', + 'url' => 'https://live.staticflickr.com/8572/16055522574_ce77fde14e_b.jpg', + 'height' => 680, + 'width' => 1024 + ], + 'author' => [ + '@type' => 'Person', + 'name' => 'desescribir', + 'sameAs' => 'https://www.flickr.com/photos/desescribir/' + ], + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'Flickr', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.flickr.com/images/opensearch-flickr-logo.png', + 'width' => 64, + 'height' => 64 + ] + ], + 'description' => 'Explore this photo album by desescribir on Flickr!' + ], + 'oEmbed' => [ + 'type' => 'rich', + 'flickr_type' => 'album', + 'title' => 'Günther Förg. Verfolgen Malerei / Fundación Luís Seoane', + 'author_name' => 'desescribir', + 'author_url' => 'https://www.flickr.com/photos/desescribir/', + 'width' => 800, + 'height' => 600, + 'web_page' => 'https://www.flickr.com/photos/desescribir/sets/72157650686499888', + 'thumbnail_url' => 'https://live.staticflickr.com/8572/16055522574_ce77fde14e_b.jpg', + 'thumbnail_width' => 800, + 'thumbnail_height' => 600, + 'web_page_short_url' => 'https://flic.kr/s/aHsk8hUbqq', + 'license_url' => 'https://creativecommons.org/licenses/by-nc-nd/2.0/', + 'html' => '\'Günther', + 'version' => '1.0', + 'cache_age' => 3600, + 'provider_name' => 'Flickr', + 'provider_url' => 'https://www.flickr.com/' + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'WebSite', + 'name' => 'Flickr', + 'url' => 'https://www.flickr.com/', + 'potentialAction' => [ + '@type' => 'SearchAction', + 'target' => 'https://www.flickr.com/search?text={search_term_string}&structured=yes', + 'query-input' => 'required name=search_term_string' + ] + ], + [ + '@context' => 'http://schema.org/', + '@type' => 'Organization', + 'url' => 'http://www.flickr.com/', + 'logo' => 'https://www.flickr.com/images/opensearch-flickr-logo.png' + ], + [ + '@context' => 'http://schema.org/', + '@type' => 'Person', + 'name' => 'Flickr', + 'url' => 'https://www.flickr.com/', + 'sameAs' => [ + 'https://www.facebook.com/flickr', + 'https://instagram.com/flickr', + 'https://flickr.tumblr.com/', + 'https://twitter.com/flickr', + 'https://www.pinterest.com/flickr' + ] + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'BlogPosting', + 'mainEntityOfPage' => [ + '@type' => 'WebPage', + '@id' => 'https://www.flickr.com/photos/desescribir/sets/72157650686499888' + ], + 'headline' => 'Günther Förg. Verfolgen Malerei / Fundación Luís Seoane', + 'image' => [ + '@type' => 'ImageObject', + 'url' => 'https://live.staticflickr.com/8572/16055522574_ce77fde14e_b.jpg', + 'height' => 680, + 'width' => 1024 + ], + 'author' => [ + '@type' => 'Person', + 'name' => 'desescribir', + 'sameAs' => 'https://www.flickr.com/photos/desescribir/' + ], + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'Flickr', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.flickr.com/images/opensearch-flickr-logo.png', + 'width' => 64, + 'height' => 64 + ] + ], + 'description' => 'Explore this photo album by desescribir on Flickr!' + ] + ] +]; diff --git a/tests/fixtures/www.flickr.com.photos-desescribir.php b/tests/fixtures/www.flickr.com.photos-desescribir.php new file mode 100644 index 00000000..cf7efc91 --- /dev/null +++ b/tests/fixtures/www.flickr.com.photos-desescribir.php @@ -0,0 +1,127 @@ + 'desescribir', + 'authorUrl' => 'https://www.flickr.com/photos/desescribir/', + 'cms' => null, + 'code' => [ + 'html' => '\'Cantos', + 'width' => 800, + 'height' => 600, + 'ratio' => 75.0 + ], + 'description' => 'Explore desescribir\'s 618 photos on Flickr!', + 'favicon' => 'https://combo.staticflickr.com/pw/favicon.ico', + 'feeds' => [ + 'https://www.flickr.com/services/feeds/photos_public.gne?id=34912442@N03&lang=en-us&format=atom' + ], + 'icon' => 'https://combo.staticflickr.com/pw/images/favicons/favicon-120.png', + 'image' => 'https://live.staticflickr.com/8765/17244790083_d2f40f713f_b.jpg', + 'keywords' => [], + 'language' => 'en-us', + 'languages' => [], + 'license' => 'https://creativecommons.org/licenses/by-nc-nd/2.0/', + 'providerName' => 'Flickr', + 'providerUrl' => 'https://www.flickr.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'desescribir', + 'url' => 'https://www.flickr.com/photos/desescribir/', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'WebSite', + 'name' => 'Flickr', + 'url' => 'https://www.flickr.com/', + 'potentialAction' => [ + '@type' => 'SearchAction', + 'target' => 'https://www.flickr.com/search?text={search_term_string}&structured=yes', + 'query-input' => 'required name=search_term_string' + ] + ], + 'oEmbed' => [ + 'type' => 'rich', + 'flickr_type' => 'photostream', + 'title' => 'desescribir', + 'author_name' => 'desescribir', + 'author_url' => 'https://www.flickr.com/photos/desescribir/', + 'width' => 800, + 'height' => 600, + 'url' => 'https://www.flickr.com/photos/desescribir/', + 'web_page' => 'https://www.flickr.com/photos/desescribir/', + 'thumbnail_url' => 'https://live.staticflickr.com/8765/17244790083_d2f40f713f_b.jpg', + 'thumbnail_width' => 800, + 'thumbnail_height' => 600, + 'web_page_short_url' => 'https://flic.kr/ps/wRmwB', + 'license_url' => 'https://creativecommons.org/licenses/by-nc-nd/2.0/', + 'html' => '\'Cantos', + 'version' => '1.0', + 'cache_age' => 3600, + 'provider_name' => 'Flickr', + 'provider_url' => 'https://www.flickr.com/' + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'WebSite', + 'name' => 'Flickr', + 'url' => 'https://www.flickr.com/', + 'potentialAction' => [ + '@type' => 'SearchAction', + 'target' => 'https://www.flickr.com/search?text={search_term_string}&structured=yes', + 'query-input' => 'required name=search_term_string' + ] + ], + [ + '@context' => 'http://schema.org/', + '@type' => 'Organization', + 'url' => 'http://www.flickr.com/', + 'logo' => 'https://www.flickr.com/images/opensearch-flickr-logo.png' + ], + [ + '@context' => 'http://schema.org/', + '@type' => 'Person', + 'name' => 'Flickr', + 'url' => 'https://www.flickr.com/', + 'sameAs' => [ + 'https://www.facebook.com/flickr', + 'https://instagram.com/flickr', + 'https://flickr.tumblr.com/', + 'https://twitter.com/flickr', + 'https://plus.google.com/+flickr', + 'https://www.pinterest.com/flickr' + ] + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'BlogPosting', + 'mainEntityOfPage' => [ + '@type' => 'WebPage', + '@id' => 'https://www.flickr.com/photos/desescribir/' + ], + 'headline' => 'desescribir', + 'image' => [ + '@type' => 'ImageObject', + 'url' => 'https://live.staticflickr.com/8765/17244790083_d2f40f713f_z.jpg', + 'height' => 454, + 'width' => 640 + ], + 'author' => [ + '@type' => 'Person', + 'name' => 'desescribir', + 'sameAs' => 'https://www.flickr.com/photos/desescribir/' + ], + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'Flickr', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.flickr.com/images/opensearch-flickr-logo.png', + 'width' => 64, + 'height' => 64 + ] + ], + 'description' => 'Explore desescribir\'s 618 photos on Flickr!' + ] + ] +]; diff --git a/tests/fixtures/www.hookem.com.story-texas-shortstop-joe-baker-arrested-public-intoxication.php b/tests/fixtures/www.hookem.com.story-texas-shortstop-joe-baker-arrested-public-intoxication.php new file mode 100644 index 00000000..6724865f --- /dev/null +++ b/tests/fixtures/www.hookem.com.story-texas-shortstop-joe-baker-arrested-public-intoxication.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://eu.hookem.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Hookem', + 'providerUrl' => 'https://eu.hookem.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => '404 Not Found', + 'url' => 'https://eu.hookem.com/', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.itmedia.co.jp.news-articles-2410-28-news159.html.php b/tests/fixtures/www.itmedia.co.jp.news-articles-2410-28-news159.html.php new file mode 100644 index 00000000..38e84091 --- /dev/null +++ b/tests/fixtures/www.itmedia.co.jp.news-articles-2410-28-news159.html.php @@ -0,0 +1,87 @@ + '@itmedia_news', + 'authorUrl' => 'https://twitter.com/itmedia_news', + 'cms' => null, + 'code' => null, + 'description' => 'さくらインターネットが、2025年3月期第2四半期累計(24年4月〜9月)の連結決算を発表した。売上高は132億7100万円(前年同期比28.3%増)、営業利益は12億9500万円(同419.4%増)だった。生成AI需要によってGPUクラウドサービスが伸長したという。', + 'favicon' => 'https://www.itmedia.co.jp/favicon.ico', + 'feeds' => [ + 'https://rss.itmedia.co.jp/rss/2.0/news_bursts.xml' + ], + 'icon' => null, + 'image' => 'https://image.itmedia.co.jp/news/articles/2410/28/cover_news159.jpg', + 'keywords' => [ + '速報', + 'ai', + '生成aiニュース', + 'クラウドユーザー', + 'ロボット・ai' + ], + 'language' => 'ja', + 'languages' => [], + 'license' => null, + 'providerName' => 'ITmedia NEWS', + 'providerUrl' => 'https://www.itmedia.co.jp/', + 'publishedTime' => '2024-10-28 17:55:00', + 'redirect' => null, + 'title' => 'さくらインターネット、営業利益が前年同期比420%増 GPUクラウド伸長で“生成AIフィーバー”? 上期決算', + 'url' => 'https://www.itmedia.co.jp/news/articles/2410/28/news159.html', + 'linkedData' => [ + '@context' => 'https://schema.org/', + '@type' => 'NewsArticle', + 'mainEntityOfPage' => [ + '@type' => 'WebPage', + '@id' => 'https://www.itmedia.co.jp/news/articles/2410/28/news159.html' + ], + 'image' => [ + 'https://image.itmedia.co.jp/images/logo/1200x630_500x500_news.gif' + ], + 'datePublished' => '2024-10-28T17:55:00Z', + 'dateModified' => '2024-10-28T18:05:00Z', + 'headline' => 'さくらインターネット、営業利益が前年同期比420%増 GPUクラウド伸長で“生成AIフィーバー”? 上期決算', + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'ITmedia NEWS', + 'url' => 'https://www.itmedia.co.jp/news/', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://image.itmedia.co.jp/images/logo/amp_publisher_news.gif' + ] + ], + 'description' => 'さくらインターネットが、2025年3月期第2四半期累計(24年4月〜9月)の連結決算を発表した。売上高は132億7100万円(前年同期比28.3%増)、営業利益は12億9500万円(同419.4%増)だった。生成AI需要によってGPUクラウドサービスが伸長したという。', + 'articleSection' => 'ニュース', + 'keywords' => '速報,AI,生成AIニュース,クラウドユーザー,ロボット・AI' + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@context' => 'https://schema.org/', + '@type' => 'NewsArticle', + 'mainEntityOfPage' => [ + '@type' => 'WebPage', + '@id' => 'https://www.itmedia.co.jp/news/articles/2410/28/news159.html' + ], + 'image' => [ + 'https://image.itmedia.co.jp/images/logo/1200x630_500x500_news.gif' + ], + 'datePublished' => '2024-10-28T17:55:00Z', + 'dateModified' => '2024-10-28T18:05:00Z', + 'headline' => 'さくらインターネット、営業利益が前年同期比420%増 GPUクラウド伸長で“生成AIフィーバー”? 上期決算', + 'publisher' => [ + '@type' => 'Organization', + 'name' => 'ITmedia NEWS', + 'url' => 'https://www.itmedia.co.jp/news/', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://image.itmedia.co.jp/images/logo/amp_publisher_news.gif' + ] + ], + 'description' => 'さくらインターネットが、2025年3月期第2四半期累計(24年4月〜9月)の連結決算を発表した。売上高は132億7100万円(前年同期比28.3%増)、営業利益は12億9500万円(同419.4%増)だった。生成AI需要によってGPUクラウドサービスが伸長したという。', + 'articleSection' => 'ニュース', + 'keywords' => '速報,AI,生成AIニュース,クラウドユーザー,ロボット・AI' + ] + ] +]; diff --git a/tests/fixtures/www.kickstarter.com.projects-1452363698-good-seed-craft-veggie-burgers.php b/tests/fixtures/www.kickstarter.com.projects-1452363698-good-seed-craft-veggie-burgers.php new file mode 100644 index 00000000..968da7ef --- /dev/null +++ b/tests/fixtures/www.kickstarter.com.projects-1452363698-good-seed-craft-veggie-burgers.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://www.kickstarter.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => null, + 'providerName' => 'Kickstarter', + 'providerUrl' => 'https://www.kickstarter.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Just a moment...', + 'url' => 'https://www.kickstarter.com/projects/1452363698/good-seed-craft-veggie-burgers', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.meetup.com.es-gpul-labs-events-248885422.php b/tests/fixtures/www.meetup.com.es-gpul-labs-events-248885422.php new file mode 100644 index 00000000..abfe9cee --- /dev/null +++ b/tests/fixtures/www.meetup.com.es-gpul-labs-events-248885422.php @@ -0,0 +1,53 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Not a Meetup member yet? Log in and find groups that host online or in person events and meet people in your local community who share your interests.', + 'favicon' => 'https://secure.meetupstatic.com/next/images/general/favicon.ico', + 'feeds' => [], + 'icon' => 'https://secure.meetupstatic.com/next/images/general/m_swarm_120x120.png', + 'image' => 'https://secure.meetupstatic.com/next/images/shared/meetup-logo.jpg', + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => null, + 'providerName' => 'Meetup', + 'providerUrl' => 'https://www.meetup.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Login to Meetup | Meetup', + 'url' => 'https://www.meetup.com/login/?returnUri=https%3A%2F%2Fwww.meetup.com%2Fgpul-labs%2Fevents%2F248885422%2F', + 'linkedData' => [ + '@type' => 'Organization', + '@context' => 'https://schema.org/', + 'url' => 'https://www.meetup.com/login/', + 'name' => 'Meetup', + 'logo' => 'https://secure.meetupstatic.com/next/images/general/m_swarm_630x630.png', + 'sameAs' => [ + 'https://www.facebook.com/meetup/', + 'https://twitter.com/Meetup/', + 'https://www.youtube.com/meetup', + 'https://www.instagram.com/meetup/' + ] + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@type' => 'Organization', + '@context' => 'https://schema.org/', + 'url' => 'https://www.meetup.com/login/', + 'name' => 'Meetup', + 'logo' => 'https://secure.meetupstatic.com/next/images/general/m_swarm_630x630.png', + 'sameAs' => [ + 'https://www.facebook.com/meetup/', + 'https://twitter.com/Meetup/', + 'https://www.youtube.com/meetup', + 'https://www.instagram.com/meetup/' + ] + ] + ] +]; diff --git a/tests/fixtures/www.pinterest.com.pin-106890191127977979.php b/tests/fixtures/www.pinterest.com.pin-106890191127977979.php new file mode 100644 index 00000000..a29ccc4f --- /dev/null +++ b/tests/fixtures/www.pinterest.com.pin-106890191127977979.php @@ -0,0 +1,46 @@ + 'Leslie Carruthers', + 'authorUrl' => 'https://www.pinterest.com/thesearchguru/', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 450, + 'height' => 663, + 'ratio' => 147.333 + ], + 'description' => null, + 'favicon' => 'https://s.pinimg.com/webapp/favicon_48x48-7470a30d.png', + 'feeds' => [], + 'icon' => 'https://s.pinimg.com/webapp/logo_transparent_144x144-3da7a67b.png', + 'image' => 'https://i.pinimg.com/236x/b5/34/13/b53413787f3a42c8b9d5b08a6fbb2124.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Pinterest', + 'providerUrl' => 'https://www.pinterest.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Pourparler', + 'url' => 'https://www.pinterest.com/pin/106890191127977979/', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'rich', + 'provider_name' => 'Pinterest', + 'provider_url' => 'https://www.pinterest.com/', + 'width' => 450, + 'height' => 663, + 'title' => 'Pourparler', + 'author_name' => 'Leslie Carruthers', + 'author_url' => 'https://www.pinterest.com/thesearchguru/', + 'html' => '', + 'thumbnail_url' => 'https://i.pinimg.com/236x/b5/34/13/b53413787f3a42c8b9d5b08a6fbb2124.jpg', + 'thumbnail_width' => 236, + 'thumbnail_height' => 295 + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.html.php b/tests/fixtures/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.html.php new file mode 100644 index 00000000..14839b25 --- /dev/null +++ b/tests/fixtures/www.politico.com.story-2013-12-presidents-barack-obama-george-w-bush-second-term-101314.html.php @@ -0,0 +1,27 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => null, + 'favicon' => 'https://www.politico.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => null, + 'providerName' => 'Politico', + 'providerUrl' => 'https://www.politico.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Just a moment...', + 'url' => 'https://www.politico.com/story/2013/12/presidents-barack-obama-george-w-bush-second-term-101314.html', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.reddit.com.r-investing-comments-7pfpeq-buffett_on_cyrptocurrencies_i_can_say_almost_with.php b/tests/fixtures/www.reddit.com.r-investing-comments-7pfpeq-buffett_on_cyrptocurrencies_i_can_say_almost_with.php new file mode 100644 index 00000000..edf0bab8 --- /dev/null +++ b/tests/fixtures/www.reddit.com.r-investing-comments-7pfpeq-buffett_on_cyrptocurrencies_i_can_say_almost_with.php @@ -0,0 +1,45 @@ + 'dennisrieves', + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '
Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'
by u/dennisrieves in investing
', + 'width' => null, + 'height' => 316, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'https://www.reddit.com/favicon.ico', + 'feeds' => [], + 'icon' => 'https://www.redditstatic.com/shreddit/assets/favicon/76x76.png', + 'image' => null, + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => null, + 'providerName' => 'reddit', + 'providerUrl' => 'https://www.reddit.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'', + 'url' => 'https://www.reddit.com/r/investing/comments/7pfpeq/buffett_on_cyrptocurrencies_i_can_say_almost_with/?rdt=46144', + 'linkedData' => [], + 'oEmbed' => [ + 'author_name' => 'dennisrieves', + 'html' => '
+Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'
by +u/dennisrieves in +investing +
+', + 'provider_name' => 'reddit', + 'provider_url' => 'https://www.reddit.com/', + 'title' => 'Buffett on cyrptocurrencies: \'I can say almost with certainty that they will come to a bad ending\'', + 'type' => 'rich', + 'height' => 316 + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.scribd.com.doc-110799637-synthesis-of-knowledge-effects-of-fire-and-thinning-treatments-on-understory-vegetation-in-dry-u-s-forests.php b/tests/fixtures/www.scribd.com.doc-110799637-synthesis-of-knowledge-effects-of-fire-and-thinning-treatments-on-understory-vegetation-in-dry-u-s-forests.php new file mode 100644 index 00000000..9fcabe2e --- /dev/null +++ b/tests/fixtures/www.scribd.com.doc-110799637-synthesis-of-knowledge-effects-of-fire-and-thinning-treatments-on-understory-vegetation-in-dry-u-s-forests.php @@ -0,0 +1,101 @@ + 'Joint Fire Science Program', + 'authorUrl' => 'https://www.scribd.com/user/151878975/Joint-Fire-Science-Program', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => 'A review of current literature on studies that address effects of prescribed fire and mechanical thinning treatments on understory vegetation, and the effects of prescribed burning on rare, threatened and endangered species. The studies\' outcomes are presented in two sets of tables: (1) functional group results, and (2) species-specific results.', + 'favicon' => 'https://s-f.scribdassets.com/scribd.ico?64c27a3f1?v=5', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://imgv2-2-f.scribdassets.com/img/document/110799637/111x142/9fc8621525/1718028294?v=1', + 'keywords' => [], + 'language' => 'en', + 'languages' => [ + 'x-default' => 'https://www.scribd.com/document/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests', + 'en' => 'https://www.scribd.com/document/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests' + ], + 'license' => null, + 'providerName' => 'Scribd', + 'providerUrl' => 'https://www.scribd.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Synthesis of Knowledge: Effects of Fire and Thinning Treatments on Understory Vegetation in Dry U.S. Forests', + 'url' => 'http://www.scribd.com/doc/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'MediaObject', + 'additionalType' => 'Product', + 'name' => 'Synthesis of Knowledge: Effects of Fire and Thinning Treatments on Understory Vegetation in Dry U.S. Forests', + 'image' => [ + 'https://imgv2-1-f.scribdassets.com/img/document/110799637/149x198/ca766a678b/1521312948?v=1', + 'https://imgv2-1-f.scribdassets.com/img/document/110799637/298x396/889f159160/1521312948?v=1' + ], + 'aggregateRating' => [ + '@type' => 'AggregateRating', + 'ratingValue' => 5.0, + 'ratingCount' => 1 + ], + 'author' => [ + '@type' => 'Person', + 'name' => 'Joint Fire Science Program' + ], + 'description' => 'A review of current literature on studies that address effects of prescribed fire and mechanical thinning treatments on understory vegetation, and the effects of prescribed burning on rare, threatened and endangered species. The studies\' outcomes are presented in two sets of tables: (1) functional group results, and (2) species-specific results.', + 'url' => 'https://www.scribd.com/document/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests', + 'hasPart' => [ + '@type' => 'WebPageElement', + 'cssSelector' => '.blurred_page' + ] + ], + 'oEmbed' => [ + 'type' => 'rich', + 'version' => '1.0', + 'provider_name' => 'Scribd', + 'provider_url' => 'https://www.scribd.com/', + 'cache_age' => 604800, + 'title' => 'Synthesis of Knowledge: Effects of Fire and Thinning Treatments on Understory Vegetation in Dry U.S. Forests', + 'author_name' => 'Joint Fire Science Program', + 'author_url' => 'https://www.scribd.com/user/151878975/Joint-Fire-Science-Program', + 'thumbnail_url' => 'https://imgv2-2-f.scribdassets.com/img/document/110799637/111x142/9fc8621525/1718028294?v=1', + 'thumbnail_width' => 164, + 'thumbnail_height' => 212, + 'html' => '', + 'url' => 'http://www.scribd.com/doc/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests' + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'MediaObject', + 'additionalType' => 'Product', + 'name' => 'Synthesis of Knowledge: Effects of Fire and Thinning Treatments on Understory Vegetation in Dry U.S. Forests', + 'image' => [ + 'https://imgv2-1-f.scribdassets.com/img/document/110799637/149x198/ca766a678b/1521312948?v=1', + 'https://imgv2-1-f.scribdassets.com/img/document/110799637/298x396/889f159160/1521312948?v=1' + ], + 'aggregateRating' => [ + '@type' => 'AggregateRating', + 'ratingValue' => 5.0, + 'ratingCount' => 1 + ], + 'author' => [ + '@type' => 'Person', + 'name' => 'Joint Fire Science Program' + ], + 'description' => 'A review of current literature on studies that address effects of prescribed fire and mechanical thinning treatments on understory vegetation, and the effects of prescribed burning on rare, threatened and endangered species. The studies\' outcomes are presented in two sets of tables: (1) functional group results, and (2) species-specific results.', + 'url' => 'https://www.scribd.com/document/110799637/Synthesis-of-Knowledge-Effects-of-Fire-and-Thinning-Treatments-on-Understory-Vegetation-in-Dry-U-S-Forests', + 'hasPart' => [ + '@type' => 'WebPageElement', + 'cssSelector' => '.blurred_page' + ] + ] + ] +]; diff --git a/tests/fixtures/www.soundhelix.com.examples-mp3-soundhelix-song-1.mp3.php b/tests/fixtures/www.soundhelix.com.examples-mp3-soundhelix-song-1.mp3.php new file mode 100644 index 00000000..1d646d7b --- /dev/null +++ b/tests/fixtures/www.soundhelix.com.examples-mp3-soundhelix-song-1.mp3.php @@ -0,0 +1,32 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'https://www.soundhelix.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => null, + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Soundhelix', + 'providerUrl' => 'https://www.soundhelix.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => null, + 'url' => 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.spreaker.com.user-angelclark-angel-clark-ice-cream-tocos.php b/tests/fixtures/www.spreaker.com.user-angelclark-angel-clark-ice-cream-tocos.php new file mode 100644 index 00000000..4cbbb80f --- /dev/null +++ b/tests/fixtures/www.spreaker.com.user-angelclark-angel-clark-ice-cream-tocos.php @@ -0,0 +1,36 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => null, + 'description' => 'Listen in to popular podcasts and radio shows from around the world or start your own with Spreaker!', + 'favicon' => 'https://d1sojsgu0jwtb7.cloudfront.net/images/favicons/spreaker/favicon.ico', + 'feeds' => [], + 'icon' => 'https://d1sojsgu0jwtb7.cloudfront.net/images/favicons/spreaker/apple-touch-icon.png', + 'image' => 'https://d1sojsgu0jwtb7.cloudfront.net/images/og_image.jpg', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'Spreaker', + 'providerUrl' => 'https://www.spreaker.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Spreaker', + 'url' => 'https://www.spreaker.com/user/angelclark/angel-clark-ice-cream-tocos', + 'linkedData' => [], + 'oEmbed' => [ + 'response' => [ + 'error' => [ + 'messages' => [ + 'The input URL does not match any supported resource on Spreaker.' + ], + 'code' => 404 + ] + ] + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.ted.com.talks-george_monbiot_for_more_wonder_rewild_the_world.07a0d4dfc7fba14d52025577270bbe9c.php b/tests/fixtures/www.ted.com.talks-george_monbiot_for_more_wonder_rewild_the_world.07a0d4dfc7fba14d52025577270bbe9c.php new file mode 100644 index 00000000..311495ee --- /dev/null +++ b/tests/fixtures/www.ted.com.talks-george_monbiot_for_more_wonder_rewild_the_world.07a0d4dfc7fba14d52025577270bbe9c.php @@ -0,0 +1,92 @@ + 'George Monbiot', + 'authorUrl' => 'https://www.ted.com/speakers/george_monbiot', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 560, + 'height' => 316, + 'ratio' => 56.429 + ], + 'description' => 'Wolves were once native to the US\' Yellowstone National Park -- until hunting wiped them out. But when, in 1995, the wolves began to come back (thanks to an aggressive management program), something interesting happened: the rest of the park began to find a new, more healthful balance. In a bold thought experiment, George Monbiot imagines a wilder world in which humans work to restore the complex, lost natural food chains that once surrounded us.', + 'favicon' => 'https://www.ted.com/favicon.ico', + 'feeds' => [], + 'icon' => 'https://pa.tedcdn.com/apple-touch-icon-precomposed.png', + 'image' => 'https://pi.tedcdn.com/r/pe.tedcdn.com/images/ted/b4a648817c1a2102dc53dc2147bb1af2785067f0_1600x1200.jpg?h=316&w=560', + 'keywords' => [ + 'ted', + 'talks', + 'climate change', + 'environment', + 'science', + 'sustainability', + 'animals', + 'community', + 'activism', + 'biodiversity', + 'deextinction', + 'conservation', + 'ecology', + 'ocean' + ], + 'language' => null, + 'languages' => [ + 'x-default' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world', + 'el' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=el', + 'en' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=en', + 'vi' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=vi', + 'it' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=it', + 'ar' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=ar', + 'pt-BR' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=pt-br', + 'cs' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=cs', + 'es' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=es', + 'ru' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=ru', + 'nl' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=nl', + 'pt' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=pt', + 'zh-Hant' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=zh-tw', + 'tr' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=tr', + 'zh-Hans' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=zh-cn', + 'ro' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=ro', + 'pl' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=pl', + 'fr' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=fr', + 'bg' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=bg', + 'de' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=de', + 'da' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=da', + 'hu' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=hu', + 'ja' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=ja', + 'he' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=he', + 'sr' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=sr', + 'ko' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=ko', + 'uk' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world?language=uk' + ], + 'license' => null, + 'providerName' => 'TED', + 'providerUrl' => 'https://www.ted.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'George Monbiot: For more wonder, rewild the world', + 'url' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world', + 'linkedData' => [], + 'oEmbed' => [ + 'type' => 'video', + 'version' => '1.0', + 'width' => 560, + 'height' => 316, + 'title' => 'George Monbiot: For more wonder, rewild the world', + 'description' => 'Wolves were once native to the US\' Yellowstone National Park -- until hunting wiped them out. But when, in 1995, the wolves began to come back (thanks to an aggressive management program), something interesting happened: the rest of the park began to find a new, more healthful balance. In a bold thought experiment, George Monbiot imagines a wilder world in which humans work to restore the complex, lost natural food chains that once surrounded us.', + 'url' => 'https://www.ted.com/talks/george_monbiot_for_more_wonder_rewild_the_world', + 'author_name' => 'George Monbiot', + 'provider_name' => 'TED', + 'provider_url' => 'https://www.ted.com/', + 'cache_age' => 300, + 'thumbnail_url' => 'https://pi.tedcdn.com/r/pe.tedcdn.com/images/ted/b4a648817c1a2102dc53dc2147bb1af2785067f0_1600x1200.jpg?h=316&w=560', + 'thumbnail_width' => 560, + 'thumbnail_height' => 316, + 'author_url' => 'https://www.ted.com/speakers/george_monbiot', + 'html' => '' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.tiktok.com.a3noticias-video-6806030056956251397.php b/tests/fixtures/www.tiktok.com.a3noticias-video-6806030056956251397.php new file mode 100644 index 00000000..08ae7f45 --- /dev/null +++ b/tests/fixtures/www.tiktok.com.a3noticias-video-6806030056956251397.php @@ -0,0 +1,49 @@ + 'Antena 3 Noticias', + 'authorUrl' => 'https://www.tiktok.com/@a3noticias', + 'cms' => null, + 'code' => [ + 'html' => '
@a3noticias

Nuestro #AplausoSanitario más sincero. Para todos. Y recuerda, #QuédateEnCasa

♬ Resistiré - Duo Dinamico
', + 'width' => null, + 'height' => null, + 'ratio' => null + ], + 'description' => null, + 'favicon' => 'https://www.tiktok.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://p77-sign-va.tiktokcdn.com/obj/tos-maliva-p-0068/165175e006354d838501378cfb325b79_1584652367?x-expires=1718204400&x-signature=weANzY8AXzX93c5j7jm34neMhWY%3D', + 'keywords' => [], + 'language' => 'en', + 'languages' => [], + 'license' => null, + 'providerName' => 'TikTok', + 'providerUrl' => 'https://www.tiktok.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Nuestro #AplausoSanitario más sincero. Para todos. Y recuerda, #QuédateEnCasa', + 'url' => 'https://www.tiktok.com/@a3noticias/video/6806030056956251397', + 'linkedData' => [], + 'oEmbed' => [ + 'version' => '1.0', + 'type' => 'video', + 'title' => 'Nuestro #AplausoSanitario más sincero. Para todos. Y recuerda, #QuédateEnCasa', + 'author_url' => 'https://www.tiktok.com/@a3noticias', + 'author_name' => 'Antena 3 Noticias', + 'width' => '100%', + 'height' => '100%', + 'html' => '
@a3noticias

Nuestro #AplausoSanitario más sincero. Para todos. Y recuerda, #QuédateEnCasa

♬ Resistiré - Duo Dinamico
', + 'thumbnail_width' => 480, + 'thumbnail_height' => 848, + 'thumbnail_url' => 'https://p77-sign-va.tiktokcdn.com/obj/tos-maliva-p-0068/165175e006354d838501378cfb325b79_1584652367?x-expires=1718204400&x-signature=weANzY8AXzX93c5j7jm34neMhWY%3D', + 'provider_url' => 'https://www.tiktok.com/', + 'provider_name' => 'TikTok', + 'author_unique_id' => 'a3noticias', + 'embed_product_id' => '6806030056956251397', + 'embed_type' => 'video' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.twitch.tv.twit.php b/tests/fixtures/www.twitch.tv.twit.php new file mode 100644 index 00000000..8195180d --- /dev/null +++ b/tests/fixtures/www.twitch.tv.twit.php @@ -0,0 +1,36 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '
+ +', + 'width' => 620, + 'height' => 378, + 'ratio' => 60.968 + ], + 'description' => 'Twitch is the world\'s leading video platform and community for gamers.', + 'favicon' => 'https://static.twitchcdn.net/assets/favicon-32-e29e246c157142c94346.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://static-cdn.jtvnw.net/ttv-static-metadata/twitch_logo3.jpg', + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Twitch', + 'providerUrl' => 'https://www.twitch.tv/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Twitch', + 'url' => 'https://www.twitch.tv/twit', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.twitch.tv.videos-106400740.php b/tests/fixtures/www.twitch.tv.videos-106400740.php new file mode 100644 index 00000000..d8b95775 --- /dev/null +++ b/tests/fixtures/www.twitch.tv.videos-106400740.php @@ -0,0 +1,36 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '
+ +', + 'width' => 620, + 'height' => 378, + 'ratio' => 60.968 + ], + 'description' => 'Twitch is the world\'s leading video platform and community for gamers.', + 'favicon' => 'https://static.twitchcdn.net/assets/favicon-32-e29e246c157142c94346.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://static-cdn.jtvnw.net/ttv-static-metadata/twitch_logo3.jpg', + 'keywords' => [], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Twitch', + 'providerUrl' => 'https://www.twitch.tv/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Twitch', + 'url' => 'https://www.twitch.tv/videos/106400740', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.twitch.tv.videos-72749628.php b/tests/fixtures/www.twitch.tv.videos-72749628.php new file mode 100644 index 00000000..6c465004 --- /dev/null +++ b/tests/fixtures/www.twitch.tv.videos-72749628.php @@ -0,0 +1,107 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 640, + 'height' => 360, + 'ratio' => 56.25 + ], + 'description' => 'riotgames went live on Twitch. Catch up on their League of Legends VOD now.', + 'favicon' => 'https://assets.twitch.tv/assets/favicon-32-e29e246c157142c94346.png', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://static-cdn.jtvnw.net/cf_vods/d2nvs31859zcd8/d44201bac3_riotgames_21876932832_470478938/thumb/thumb0-640x360.jpg', + 'keywords' => [], + 'language' => null, + 'languages' => [ + 'bg' => 'https://www.twitch.tv/videos/72749628?lang=bg', + 'cs' => 'https://www.twitch.tv/videos/72749628?lang=cs', + 'da' => 'https://www.twitch.tv/videos/72749628?lang=da', + 'de' => 'https://www.twitch.tv/videos/72749628?lang=de', + 'el' => 'https://www.twitch.tv/videos/72749628?lang=el', + 'es' => 'https://www.twitch.tv/videos/72749628?lang=es', + 'es-mx' => 'https://www.twitch.tv/videos/72749628?lang=es-mx', + 'fi' => 'https://www.twitch.tv/videos/72749628?lang=fi', + 'fr' => 'https://www.twitch.tv/videos/72749628?lang=fr', + 'hu' => 'https://www.twitch.tv/videos/72749628?lang=hu', + 'it' => 'https://www.twitch.tv/videos/72749628?lang=it', + 'ja' => 'https://www.twitch.tv/videos/72749628?lang=ja', + 'ko' => 'https://www.twitch.tv/videos/72749628?lang=ko', + 'nl' => 'https://www.twitch.tv/videos/72749628?lang=nl', + 'no' => 'https://www.twitch.tv/videos/72749628?lang=no', + 'pl' => 'https://www.twitch.tv/videos/72749628?lang=pl', + 'pt' => 'https://www.twitch.tv/videos/72749628?lang=pt', + 'pt-br' => 'https://www.twitch.tv/videos/72749628?lang=pt-br', + 'ro' => 'https://www.twitch.tv/videos/72749628?lang=ro', + 'ru' => 'https://www.twitch.tv/videos/72749628?lang=ru', + 'sk' => 'https://www.twitch.tv/videos/72749628?lang=sk', + 'sv' => 'https://www.twitch.tv/videos/72749628?lang=sv', + 'th' => 'https://www.twitch.tv/videos/72749628?lang=th', + 'tr' => 'https://www.twitch.tv/videos/72749628?lang=tr', + 'vi' => 'https://www.twitch.tv/videos/72749628?lang=vi', + 'zh-cn' => 'https://www.twitch.tv/videos/72749628?lang=zh-cn', + 'zh-tw' => 'https://www.twitch.tv/videos/72749628?lang=zh-tw', + 'x-default' => 'https://www.twitch.tv/videos/72749628' + ], + 'license' => null, + 'providerName' => 'Twitch', + 'providerUrl' => 'https://www.twitch.tv/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'EU LCS Summer - Week 3 Day 1: FNC vs. S04 | H2K vs. G2 (EULCS2) - riotgames on Twitch', + 'url' => 'https://www.twitch.tv/videos/72749628', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@graph' => [ + [ + '@type' => 'VideoObject', + 'description' => 'riotgames went live on Twitch. Catch up on their League of Legends VOD now.', + 'embedUrl' => 'https://www.twitch.tv/videos/72749628', + 'name' => 'EU LCS Summer - Week 3 Day 1: FNC vs. S04 | H2K vs. G2 (EULCS2)', + 'thumbnailUrl' => [ + 'https://static-cdn.jtvnw.net/cf_vods/d2nvs31859zcd8/d44201bac3_riotgames_21876932832_470478938/thumb/thumb0-640x360.jpg' + ], + 'uploadDate' => '2016-06-16T13:30:57Z', + 'duration' => 'PT2180S', + 'interactionStatistic' => [ + '@type' => 'InteractionCounter', + 'interactionType' => [ + '@type' => 'http://schema.org/WatchAction' + ], + 'userInteractionCount' => 1589 + ] + ] + ] + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@graph' => [ + [ + '@type' => 'VideoObject', + 'description' => 'riotgames went live on Twitch. Catch up on their League of Legends VOD now.', + 'embedUrl' => 'https://www.twitch.tv/videos/72749628', + 'name' => 'EU LCS Summer - Week 3 Day 1: FNC vs. S04 | H2K vs. G2 (EULCS2)', + 'thumbnailUrl' => [ + 'https://static-cdn.jtvnw.net/cf_vods/d2nvs31859zcd8/d44201bac3_riotgames_21876932832_470478938/thumb/thumb0-640x360.jpg' + ], + 'uploadDate' => '2016-06-16T13:30:57Z', + 'duration' => 'PT2180S', + 'interactionStatistic' => [ + '@type' => 'InteractionCounter', + 'interactionType' => [ + '@type' => 'http://schema.org/WatchAction' + ], + 'userInteractionCount' => 1589 + ] + ] + ] + ] + ] +]; diff --git a/tests/fixtures/www.ustream.tv.channel-red-shoes-billiards-60803-camera-1.php b/tests/fixtures/www.ustream.tv.channel-red-shoes-billiards-60803-camera-1.php new file mode 100644 index 00000000..394c0920 --- /dev/null +++ b/tests/fixtures/www.ustream.tv.channel-red-shoes-billiards-60803-camera-1.php @@ -0,0 +1,53 @@ + 'redsh0es', + 'authorUrl' => 'http://www.ustream.tv/', + 'cms' => null, + 'code' => [ + 'html' => '
Live Video Streaming', + 'width' => 400, + 'height' => 320, + 'ratio' => 80.0 + ], + 'description' => 'End to end video platform for media & enterprises. Live streaming, video hosting, transcoding, monetization, distribution & delivery services for businesses.', + 'favicon' => 'http://static-cdn2.ustream.tv/favicon.ico', + 'feeds' => [], + 'icon' => 'http://static-cdn2.ustream.tv/apple-touch-icon.png', + 'image' => 'https://ustvstaticcdn2-a.akamaihd.net/i/channel/picture/1/1/9/5/11958409/11958409,120x90,r:2.jpg', + 'keywords' => [ + 'streaming', + 'streaming video', + 'video platform', + 'video hosting', + 'streaming video platform', + 'streaming video services', + 'video hosting services' + ], + 'language' => 'es', + 'languages' => [], + 'license' => null, + 'providerName' => 'IBM Video Streaming', + 'providerUrl' => 'http://www.ustream.tv/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Red Shoes Billiards 1pkt,banks camera 1', + 'url' => 'http://www.ustream.tv/channel/red-shoes-billiards-60803-camera-1', + 'linkedData' => [], + 'oEmbed' => [ + 'provider_url' => 'http://www.ustream.tv/', + 'html' => '
Live Video Streaming', + 'title' => 'Red Shoes Billiards 1pkt,banks camera 1', + 'author_name' => 'redsh0es', + 'height' => 320, + 'thumbnail_width' => 120, + 'width' => 400, + 'version' => '1.0', + 'author_url' => 'http://www.ustream.tv/', + 'thumbnail_url' => 'https://ustvstaticcdn2-a.akamaihd.net/i/channel/picture/1/1/9/5/11958409/11958409,120x90,r:2.jpg', + 'type' => 'video', + 'thumbnail_height' => 90 + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.viddler.com.v-bdce8c7.php b/tests/fixtures/www.viddler.com.v-bdce8c7.php new file mode 100644 index 00000000..7b06740b --- /dev/null +++ b/tests/fixtures/www.viddler.com.v-bdce8c7.php @@ -0,0 +1,38 @@ + null, + 'authorUrl' => null, + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 1280, + 'height' => 720, + 'ratio' => 56.25 + ], + 'description' => 'Viddler is a powerful and easy-to-use video platform that services both small and large companies. We give you the tools to connect with your audience in a unique way and we also help you leverage your videos so that you can make money.', + 'favicon' => 'https://static1.cdn-ec.viddler.com/rails/assets/layout/favicon-a9c9c887d52b5d9a765dd3468a2285b8.png', + 'feeds' => [ + 'https://www.viddler.com/rss/viddler' + ], + 'icon' => null, + 'image' => 'https://thumbs.cdn-ec.viddler.com/thumbnail_2_bdce8c7_v8.jpg', + 'keywords' => [ + 'viddler', + 'video sharing', + 'business video hosting' + ], + 'language' => null, + 'languages' => [], + 'license' => null, + 'providerName' => 'Viddler', + 'providerUrl' => 'https://www.viddler.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'Viddler Platform Overview', + 'url' => 'https://www.viddler.com/v/bdce8c7', + 'linkedData' => [], + 'oEmbed' => [], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.wired.com..1202600986b37d2c6a30336f82c671f8.php b/tests/fixtures/www.wired.com..1202600986b37d2c6a30336f82c671f8.php new file mode 100644 index 00000000..dc201b3e --- /dev/null +++ b/tests/fixtures/www.wired.com..1202600986b37d2c6a30336f82c671f8.php @@ -0,0 +1,217 @@ + 'Condé Nast', + 'authorUrl' => 'https://twitter.com/wired', + 'cms' => null, + 'code' => null, + 'description' => 'We bring you the future as it happens. From the latest in science and technology to the big stories in business and culture, we\'ve got you covered.', + 'favicon' => 'https://www.wired.com/verso/static/wired-us/assets/favicon.ico', + 'feeds' => [ + 'https://www.wired.com/feed/rss' + ], + 'icon' => 'https://www.wired.com/verso/static/wired-us/assets/favicon.ico', + 'image' => 'https://media.wired.com/photos/615e2b8ce78a8cd913bbaa76/16:9/w_1280,c_limit/wired_bug.jpg', + 'keywords' => [], + 'language' => 'en-US', + 'languages' => [], + 'license' => 'Copyright (c) Condé Nast 2025', + 'providerName' => 'WIRED', + 'providerUrl' => 'https://www.wired.com/', + 'publishedTime' => null, + 'redirect' => null, + 'title' => 'WIRED - The Latest in Technology, Science, Culture and Business', + 'url' => 'https://www.wired.com/?p=2064839', + 'linkedData' => [ + '@context' => 'https://schema.org/', + '@type' => 'Organization', + 'name' => 'WIRED', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.wired.com/verso/static/wired-us/assets/newsletter-signup-hub.jpg', + 'width' => '500px', + 'height' => '100px' + ], + 'url' => 'https://www.wired.com/' + ], + 'oEmbed' => [], + 'allLinkedData' => [ + [ + '@context' => 'https://schema.org/', + '@type' => 'Organization', + 'name' => 'WIRED', + 'logo' => [ + '@type' => 'ImageObject', + 'url' => 'https://www.wired.com/verso/static/wired-us/assets/newsletter-signup-hub.jpg', + 'width' => '500px', + 'height' => '100px' + ], + 'url' => 'https://www.wired.com/' + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'WebSite', + 'url' => 'https://www.wired.com/', + 'name' => 'WIRED', + 'headline' => 'WIRED - The Latest in Technology, Science, Culture and Business', + 'potentialAction' => [ + '@type' => 'SearchAction', + 'target' => 'https://www.wired.com/search?q={search_term_string}', + 'query-input' => 'required name=search_term_string' + ] + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ItemList', + 'itemListElement' => [ + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Sam Altman Says the GPT-5 Haters Got It All Wrong', + 'url' => 'https://www.wired.com/story/sam-altman-says-the-gpt-5-haters-got-it-all-wrong/', + 'position' => 1 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'ICE Wants to Build Out a 24/7 Social Media Surveillance Team', + 'url' => 'https://www.wired.com/story/ice-social-media-surveillance-24-7-contract/', + 'position' => 2 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'At a Conspiracy Conference in Rural Ireland, Charlie Kirk Was the Star', + 'url' => 'https://www.wired.com/story/conspiracy-conference-rural-ireland-charlie-kirk-quantum-clones/', + 'position' => 3 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Government Workers Say Their Out-of-Office Replies Were Forcibly Changed to Blame Democrats for Shutdown', + 'url' => 'https://www.wired.com/story/government-workers-say-their-out-of-office-replies-were-forcibly-changed-to-blame-democrats-for-shutdown/', + 'position' => 4 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Inside the Contentious World of Luigi Mangione Supporters', + 'url' => 'https://www.wired.com/story/inside-the-contentious-world-of-luigi-mangione-supporters/', + 'position' => 5 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Why Are Car Software Updates Still So Bad?', + 'url' => 'https://www.wired.com/story/why-are-car-software-updates-still-so-bad/', + 'position' => 6 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Watch Our Livestream Replay: Tech Went All In on Trump. Now What?', + 'url' => 'https://www.wired.com/story/livestream-tech-went-all-in-on-trump-now-what/', + 'position' => 7 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Gear News of the Week: Adobe Premiere Lands on iPhone, and Nothing Lets You Design Your Own Widgets', + 'url' => 'https://www.wired.com/story/gear-news-of-the-week-adobe-premiere-lands-on-iphone-and-nothing-lets-you-design-your-own-widgets/', + 'position' => 8 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'The Vision Pro Was an Expensive Misstep. Now Apple Has to Catch Up With Smart Glasses', + 'url' => 'https://www.wired.com/story/the-vision-pro-was-an-expensive-misstep-now-apple-has-to-catch-up-with-smart-glasses/', + 'position' => 9 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Lenovo’s Streamlined Gaming Handheld Is $120 Off', + 'url' => 'https://www.wired.com/story/legion-go-s-deal-1025/', + 'position' => 10 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Bad Bunny Has MAGA All Worked Up', + 'url' => 'https://www.wired.com/story/bad-bunny-has-maga-all-worked-up/', + 'position' => 11 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'China Is Leading the World in the Clean Energy Transition. Here\'s What That Looks Like', + 'url' => 'https://www.wired.com/story/china-clean-energy-un-climate-summit-goals/', + 'position' => 12 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'China Rolls Out Its First Talent Visa as the US Retreats on H-1Bs', + 'url' => 'https://www.wired.com/story/china-talent-immigration-visa-h1-b-policy/', + 'position' => 13 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Chatbots Play With Your Emotions to Avoid Saying Goodbye', + 'url' => 'https://www.wired.com/story/chatbots-play-with-emotions-to-avoid-saying-goodbye/', + 'position' => 14 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'The Post–Chuck Schumer Era', + 'url' => 'https://www.wired.com/story/chuck-schumer-government-shutdown/', + 'position' => 15 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'OpenAI Is Preparing to Launch a Social App for AI-Generated Videos', + 'url' => 'https://www.wired.com/story/openai-launches-sora-2-tiktok-like-app/', + 'position' => 16 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Broadcast TV Is a \'Melting Ice Cube.’ Kimmel Just Turned Up the Heat', + 'url' => 'https://www.wired.com/story/broadcast-tv-fcc-carr-kimmel/', + 'position' => 17 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'The Trump Administration Is Coming for Nonprofits. They\'re Getting Ready', + 'url' => 'https://www.wired.com/story/the-trump-administration-is-coming-for-nonprofits-theyre-getting-ready/', + 'position' => 18 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Federal Workers Are Being Told to Blame Democrats for the Shutdown', + 'url' => 'https://www.wired.com/story/government-employees-out-of-office-email-replies/', + 'position' => 19 + ], + [ + '@context' => 'https://schema.org/', + '@type' => 'ListItem', + 'name' => 'Armed Guards and Muscle Milk: Senate Investigation Reveals DOGE Takeover Details', + 'url' => 'https://www.wired.com/story/armed-guards-muscle-milk-senate-investigation-doge-takeover-details/', + 'position' => 20 + ] + ], + 'numberOfItems' => 20, + 'mainEntityOfPage' => [ + '@context' => 'https://schema.org/', + '@type' => 'CollectionPage', + '@id' => 'https://www.wired.com/' + ] + ] + ] +]; diff --git a/tests/fixtures/www.youtube.com.playlist.13d1655ccf6cbdc1fc0162c6a02f822a.php b/tests/fixtures/www.youtube.com.playlist.13d1655ccf6cbdc1fc0162c6a02f822a.php new file mode 100644 index 00000000..386ec3bf --- /dev/null +++ b/tests/fixtures/www.youtube.com.playlist.13d1655ccf6cbdc1fc0162c6a02f822a.php @@ -0,0 +1,47 @@ + 'Scadrei5', + 'authorUrl' => 'https://consent.youtube.com/user/Scadrei5', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 200, + 'height' => 113, + 'ratio' => 56.5 + ], + 'description' => null, + 'favicon' => 'https://www.google.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://i.ytimg.com/vi/CdbnVwot6lc/hqdefault.jpg', + 'keywords' => [], + 'language' => 'es', + 'languages' => [], + 'license' => null, + 'providerName' => 'YouTube', + 'providerUrl' => 'https://www.youtube.com/', + 'publishedTime' => null, + 'redirect' => 'https://consent.youtube.com/ml?continue=https://www.youtube.com/playlist?list%3DPL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST&gl=ES&hl=es&pc=yt&uxe=23983172&src=1&rffu=true', + 'title' => 'De espaldas al patriarcado', + 'url' => 'https://www.youtube.com/playlist?list=PL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST', + 'linkedData' => [], + 'oEmbed' => [ + 'title' => 'De espaldas al patriarcado', + 'author_name' => 'Scadrei5', + 'author_url' => '/user/Scadrei5', + 'type' => 'video', + 'height' => 113, + 'width' => 200, + 'version' => '1.0', + 'provider_name' => 'YouTube', + 'provider_url' => 'https://www.youtube.com/', + 'thumbnail_height' => 360, + 'thumbnail_width' => 480, + 'thumbnail_url' => 'https://i.ytimg.com/vi/CdbnVwot6lc/hqdefault.jpg', + 'html' => '', + 'url' => 'https://www.youtube.com/playlist?list=PL4qTakKkQATKOyZPJG_cAMnRtF7fAIdST' + ], + 'allLinkedData' => [] +]; diff --git a/tests/fixtures/www.youtube.com.watch.878f5352b6f0e632a763ebf05fb48b16.php b/tests/fixtures/www.youtube.com.watch.878f5352b6f0e632a763ebf05fb48b16.php new file mode 100644 index 00000000..f0ff1f73 --- /dev/null +++ b/tests/fixtures/www.youtube.com.watch.878f5352b6f0e632a763ebf05fb48b16.php @@ -0,0 +1,103 @@ + 'smshdchrb', + 'authorUrl' => 'https://www.youtube.com/@smshdchrb', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 200, + 'height' => 150, + 'ratio' => 75.0 + ], + 'description' => '7 week old fostered kittens waiting on their dinner being prepared. They had been ill with cat flu and were just starting to get their appetite back. Because...', + 'favicon' => 'https://www.youtube.com/s/desktop/ae4ecf92/img/favicon.ico', + 'feeds' => [], + 'icon' => 'https://www.youtube.com/s/desktop/ae4ecf92/img/favicon_144x144.png', + 'image' => 'https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg', + 'keywords' => [ + 'kittens', + 'cats', + 'hungry', + 'cat', + 'baby', + 'eight', + 'weeks', + 'old', + 'noisy', + 'meow', + 'funny', + 'kitties', + 'feline', + 'dinner', + 'excited', + 'loud', + 'cute', + 'pet', + 'food', + 'time', + 'felix', + 'kitty', + 'catz', + 'lolcat', + 'kitten', + 'talking', + 'adorable', + 'climbing' + ], + 'language' => 'es-ES', + 'languages' => [], + 'license' => null, + 'providerName' => 'YouTube', + 'providerUrl' => 'https://www.youtube.com/', + 'publishedTime' => '2008-10-04 13:06:22', + 'redirect' => null, + 'title' => 'Noisy kittens waiting for dinner!', + 'url' => 'https://www.youtube.com/watch?v=eiHXASgRTcA', + 'linkedData' => [ + '@context' => 'http://schema.org/', + '@type' => 'BreadcrumbList', + 'itemListElement' => [ + [ + '@type' => 'ListItem', + 'position' => 1, + 'item' => [ + '@id' => 'http://www.youtube.com/@smshdchrb', + 'name' => 'smshdchrb' + ] + ] + ] + ], + 'oEmbed' => [ + 'title' => 'Noisy kittens waiting for dinner!', + 'author_name' => 'smshdchrb', + 'author_url' => 'https://www.youtube.com/@smshdchrb', + 'type' => 'video', + 'height' => 150, + 'width' => 200, + 'version' => '1.0', + 'provider_name' => 'YouTube', + 'provider_url' => 'https://www.youtube.com/', + 'thumbnail_height' => 360, + 'thumbnail_width' => 480, + 'thumbnail_url' => 'https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg', + 'html' => '' + ], + 'allLinkedData' => [ + [ + '@context' => 'http://schema.org/', + '@type' => 'BreadcrumbList', + 'itemListElement' => [ + [ + '@type' => 'ListItem', + 'position' => 1, + 'item' => [ + '@id' => 'http://www.youtube.com/@smshdchrb', + 'name' => 'smshdchrb' + ] + ] + ] + ] + ] +]; diff --git a/tests/fixtures/youtu.be.eihxasgrtca.php b/tests/fixtures/youtu.be.eihxasgrtca.php new file mode 100644 index 00000000..8b6e24bd --- /dev/null +++ b/tests/fixtures/youtu.be.eihxasgrtca.php @@ -0,0 +1,47 @@ + 'smshdchrb', + 'authorUrl' => 'https://www.youtube.com/user/smshdchrb', + 'cms' => null, + 'code' => [ + 'html' => '', + 'width' => 200, + 'height' => 150, + 'ratio' => 75.0 + ], + 'description' => null, + 'favicon' => 'https://www.google.com/favicon.ico', + 'feeds' => [], + 'icon' => null, + 'image' => 'https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg', + 'keywords' => [], + 'language' => 'es', + 'languages' => [], + 'license' => null, + 'providerName' => 'YouTube', + 'providerUrl' => 'https://www.youtube.com/', + 'publishedTime' => null, + 'redirect' => 'https://consent.youtube.com/ml?continue=https://www.youtube.com/watch?v%3DeiHXASgRTcA%26feature%3Dyoutu.be&gl=ES&hl=es&pc=yt&uxe=23983172&src=1&rffu=true', + 'title' => 'Noisy kittens waiting for dinner!', + 'url' => 'http://youtu.be/eiHXASgRTcA', + 'linkedData' => [], + 'oEmbed' => [ + 'title' => 'Noisy kittens waiting for dinner!', + 'author_name' => 'smshdchrb', + 'author_url' => 'https://www.youtube.com/user/smshdchrb', + 'type' => 'video', + 'height' => 150, + 'width' => 200, + 'version' => '1.0', + 'provider_name' => 'YouTube', + 'provider_url' => 'https://www.youtube.com/', + 'thumbnail_height' => 360, + 'thumbnail_width' => 480, + 'thumbnail_url' => 'https://i.ytimg.com/vi/eiHXASgRTcA/hqdefault.jpg', + 'html' => '', + 'url' => 'http://youtu.be/eiHXASgRTcA' + ], + 'allLinkedData' => [] +];