add missing files for forked idiorm
This commit is contained in:
parent
fdd1c43612
commit
b8c1d622a7
|
@ -1,5 +1,12 @@
|
|||
{
|
||||
"repositories": [
|
||||
{
|
||||
"name": "fivefilters/readability.php",
|
||||
"type": "vcs",
|
||||
"url": "https://dev.tt-rss.org/fox/readability-php.git"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"fivefilters/readability.php": "^2.1"
|
||||
"fivefilters/readability.php": "dev-master"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,43 +4,44 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "985d4bb2caa672420e280a0b2bbb4715",
|
||||
"content-hash": "9b8120263fb98662acec8e8101e47465",
|
||||
"packages": [
|
||||
{
|
||||
"name": "fivefilters/readability.php",
|
||||
"version": "v2.1.0",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fivefilters/readability.php.git",
|
||||
"reference": "7617a912b6c527909168f5d41d263792f171c42a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fivefilters/readability.php/zipball/7617a912b6c527909168f5d41d263792f171c42a",
|
||||
"reference": "7617a912b6c527909168f5d41d263792f171c42a",
|
||||
"shasum": ""
|
||||
"url": "https://dev.tt-rss.org/fox/readability-php.git",
|
||||
"reference": "5ad152c70376002f043bb936d8ae5eed103fb993"
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"php": ">=7.0.0",
|
||||
"league/uri": "^6.4",
|
||||
"masterminds/html5": "^2.0",
|
||||
"php": ">=7.3.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"monolog/monolog": "^1.24",
|
||||
"phpunit/phpunit": "^6.5"
|
||||
"monolog/monolog": "^2.3",
|
||||
"phpunit/phpunit": "^9"
|
||||
},
|
||||
"suggest": {
|
||||
"monolog/monolog": "Allow logging debug information"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"andreskrey\\Readability\\": "src/"
|
||||
"fivefilters\\Readability\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"fivefilters\\Readability\\Test\\": "test"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
|
@ -48,19 +49,314 @@
|
|||
{
|
||||
"name": "Andres Rey",
|
||||
"email": "andreskrey@gmail.com",
|
||||
"role": "Lead Developer"
|
||||
"role": "Original Developer"
|
||||
},
|
||||
{
|
||||
"name": "Keyvan Minoukadeh",
|
||||
"email": "keyvan@fivefilters.org",
|
||||
"homepage": "https://www.fivefilters.org",
|
||||
"role": "Developer/Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "A PHP port of Readability.js",
|
||||
"homepage": "https://github.com/andreskrey/readability",
|
||||
"homepage": "https://github.com/fivefilters/readability.php",
|
||||
"keywords": [
|
||||
"html",
|
||||
"readability"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/fivefilters/readability.php/tree/v2.1.0"
|
||||
"time": "2022-07-16T13:23:08+00:00"
|
||||
},
|
||||
"time": "2019-07-22T21:42:25+00:00"
|
||||
{
|
||||
"name": "league/uri",
|
||||
"version": "6.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri.git",
|
||||
"reference": "2d7c87a0860f3126a39f44a8a9bf2fed402dcfea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/2d7c87a0860f3126a39f44a8a9bf2fed402dcfea",
|
||||
"reference": "2d7c87a0860f3126a39f44a8a9bf2fed402dcfea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"league/uri-interfaces": "^2.3",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"league/uri-schemes": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^v3.3.2",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"php-http/psr7-integration-tests": "^1.1",
|
||||
"phpstan/phpstan": "^1.2.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.1.0",
|
||||
"phpunit/phpunit": "^9.5.10",
|
||||
"psr/http-factory": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-fileinfo": "Needed to create Data URI from a filepath",
|
||||
"ext-intl": "Needed to improve host validation",
|
||||
"league/uri-components": "Needed to easily manipulate URI objects",
|
||||
"psr/http-factory": "Needed to use the URI factory"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Uri\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ignace Nyamagana Butera",
|
||||
"email": "nyamsprod@gmail.com",
|
||||
"homepage": "https://nyamsprod.com"
|
||||
}
|
||||
],
|
||||
"description": "URI manipulation library",
|
||||
"homepage": "https://uri.thephpleague.com",
|
||||
"keywords": [
|
||||
"data-uri",
|
||||
"file-uri",
|
||||
"ftp",
|
||||
"hostname",
|
||||
"http",
|
||||
"https",
|
||||
"middleware",
|
||||
"parse_str",
|
||||
"parse_url",
|
||||
"psr-7",
|
||||
"query-string",
|
||||
"querystring",
|
||||
"rfc3986",
|
||||
"rfc3987",
|
||||
"rfc6570",
|
||||
"uri",
|
||||
"uri-template",
|
||||
"url",
|
||||
"ws"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri/issues",
|
||||
"source": "https://github.com/thephpleague/uri/tree/6.7.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/nyamsprod",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-06-29T09:48:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/uri-interfaces",
|
||||
"version": "2.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri-interfaces.git",
|
||||
"reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
|
||||
"reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.19",
|
||||
"phpstan/phpstan": "^0.12.90",
|
||||
"phpstan/phpstan-phpunit": "^0.12.19",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.9",
|
||||
"phpunit/phpunit": "^8.5.15 || ^9.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "to use the IDNA feature",
|
||||
"symfony/intl": "to use the IDNA feature via Symfony Polyfill"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Uri\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ignace Nyamagana Butera",
|
||||
"email": "nyamsprod@gmail.com",
|
||||
"homepage": "https://nyamsprod.com"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for URI representation",
|
||||
"homepage": "http://github.com/thephpleague/uri-interfaces",
|
||||
"keywords": [
|
||||
"rfc3986",
|
||||
"rfc3987",
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/uri-interfaces/issues",
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/nyamsprod",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-06-28T04:27:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.7.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "f640ac1bdddff06ea333a920c95bbad8872429ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f640ac1bdddff06ea333a920c95bbad8872429ab",
|
||||
"reference": "f640ac1bdddff06ea333a920c95bbad8872429ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Masterminds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"keywords": [
|
||||
"HTML5",
|
||||
"dom",
|
||||
"html",
|
||||
"parser",
|
||||
"querypath",
|
||||
"serializer",
|
||||
"xml"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.7.5"
|
||||
},
|
||||
"time": "2021-07-01T14:25:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/master"
|
||||
},
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
|
@ -116,10 +412,12 @@
|
|||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"fivefilters/readability.php": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.1.0"
|
||||
}
|
||||
|
|
|
@ -42,30 +42,75 @@ namespace Composer\Autoload;
|
|||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/** @var ?string */
|
||||
private $vendorDir;
|
||||
|
||||
// PSR-4
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, int>>
|
||||
*/
|
||||
private $prefixLengthsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<int, string>>
|
||||
*/
|
||||
private $prefixDirsPsr4 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array<string, string[]>>
|
||||
*/
|
||||
private $prefixesPsr0 = array();
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
/** @var bool */
|
||||
private $useIncludePath = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private $classMap = array();
|
||||
|
||||
/** @var bool */
|
||||
private $classMapAuthoritative = false;
|
||||
|
||||
/**
|
||||
* @var bool[]
|
||||
* @psalm-var array<string, bool>
|
||||
*/
|
||||
private $missingClasses = array();
|
||||
|
||||
/** @var ?string */
|
||||
private $apcuPrefix;
|
||||
|
||||
/**
|
||||
* @var self[]
|
||||
*/
|
||||
private static $registeredLoaders = array();
|
||||
|
||||
/**
|
||||
* @param ?string $vendorDir
|
||||
*/
|
||||
public function __construct($vendorDir = null)
|
||||
{
|
||||
$this->vendorDir = $vendorDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
|
@ -75,28 +120,47 @@ class ClassLoader
|
|||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, array<int, string>>
|
||||
*/
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[] Array of classname => path
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
* @param string[] $classMap Class to filename map
|
||||
* @psalm-param array<string, string> $classMap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
|
@ -112,8 +176,10 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param string[]|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -157,10 +223,12 @@ class ClassLoader
|
|||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
|
@ -205,7 +273,9 @@ class ClassLoader
|
|||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
* @param string[]|string $paths The PSR-0 base directories
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
|
@ -221,9 +291,11 @@ class ClassLoader
|
|||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param string[]|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
|
@ -243,6 +315,8 @@ class ClassLoader
|
|||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
|
@ -265,6 +339,8 @@ class ClassLoader
|
|||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
|
@ -285,6 +361,8 @@ class ClassLoader
|
|||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
|
@ -305,14 +383,18 @@ class ClassLoader
|
|||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
|
||||
if (null === $this->vendorDir) {
|
||||
//no-op
|
||||
} elseif ($prepend) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($prepend) {
|
||||
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||
} else {
|
||||
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||
|
@ -322,6 +404,8 @@ class ClassLoader
|
|||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
|
@ -336,7 +420,7 @@ class ClassLoader
|
|||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
* @return true|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
|
@ -345,6 +429,8 @@ class ClassLoader
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -399,6 +485,11 @@ class ClassLoader
|
|||
return self::$registeredLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $ext
|
||||
* @return string|false
|
||||
*/
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
|
@ -470,6 +561,10 @@ class ClassLoader
|
|||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*
|
||||
* @param string $file
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
|
|
|
@ -18,53 +18,27 @@ use Composer\Semver\VersionParser;
|
|||
/**
|
||||
* This class is copied in every Composer installed project and available to all
|
||||
*
|
||||
* To require it's presence, you can require `composer-runtime-api ^2.0`
|
||||
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||
*
|
||||
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
private static $installed = array (
|
||||
'root' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a73e3bec45c5523910c711cf882976b71781ac9e',
|
||||
'name' => '__root__',
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a73e3bec45c5523910c711cf882976b71781ac9e',
|
||||
),
|
||||
'fivefilters/readability.php' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.1.0',
|
||||
'version' => '2.1.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => '7617a912b6c527909168f5d41d263792f171c42a',
|
||||
),
|
||||
'psr/log' =>
|
||||
array (
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
),
|
||||
),
|
||||
);
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
private static $canGetVendors;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static $installedByVendor = array();
|
||||
|
||||
/**
|
||||
|
@ -80,7 +54,6 @@ class InstalledVersions
|
|||
$packages[] = array_keys($installed['versions']);
|
||||
}
|
||||
|
||||
|
||||
if (1 === \count($packages)) {
|
||||
return $packages[0];
|
||||
}
|
||||
|
@ -88,19 +61,42 @@ class InstalledVersions
|
|||
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all package names with a specific type e.g. 'library'
|
||||
*
|
||||
* @param string $type
|
||||
* @return string[]
|
||||
* @psalm-return list<string>
|
||||
*/
|
||||
public static function getInstalledPackagesByType($type)
|
||||
{
|
||||
$packagesByType = array();
|
||||
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
foreach ($installed['versions'] as $name => $package) {
|
||||
if (isset($package['type']) && $package['type'] === $type) {
|
||||
$packagesByType[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packagesByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package is installed
|
||||
*
|
||||
* This also returns true if the package name is provided or replaced by another package
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param bool $includeDevRequirements
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInstalled($packageName)
|
||||
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (isset($installed['versions'][$packageName])) {
|
||||
return true;
|
||||
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +113,6 @@ class InstalledVersions
|
|||
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||
* @param string $packageName
|
||||
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||
|
@ -227,9 +222,26 @@ class InstalledVersions
|
|||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packageName
|
||||
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||
*/
|
||||
public static function getInstallPath($packageName)
|
||||
{
|
||||
foreach (self::getInstalled() as $installed) {
|
||||
if (!isset($installed['versions'][$packageName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||
}
|
||||
|
||||
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}
|
||||
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
|
||||
*/
|
||||
public static function getRootPackage()
|
||||
{
|
||||
|
@ -241,14 +253,38 @@ class InstalledVersions
|
|||
/**
|
||||
* Returns the raw installed.php data for custom implementations
|
||||
*
|
||||
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||
* @return array[]
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}, versions: list<string, array{pretty_version: ?string, version: ?string, aliases: ?string[], reference: ?string, replaced: ?string[], provided: ?string[]}>}
|
||||
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
|
||||
*/
|
||||
public static function getRawData()
|
||||
{
|
||||
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = include __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||
*
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
public static function getAllRawData()
|
||||
{
|
||||
return self::getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets you reload the static array from another file
|
||||
*
|
||||
|
@ -265,7 +301,7 @@ class InstalledVersions
|
|||
* @param array[] $data A vendor/composer/installed.php data set
|
||||
* @return void
|
||||
*
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}, versions: list<string, array{pretty_version: ?string, version: ?string, aliases: ?string[], reference: ?string, replaced: ?string[], provided: ?string[]}>} $data
|
||||
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
|
||||
*/
|
||||
public static function reload($data)
|
||||
{
|
||||
|
@ -275,6 +311,7 @@ class InstalledVersions
|
|||
|
||||
/**
|
||||
* @return array[]
|
||||
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
|
||||
*/
|
||||
private static function getInstalled()
|
||||
{
|
||||
|
@ -290,10 +327,22 @@ class InstalledVersions
|
|||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === self::$installed) {
|
||||
// only require the installed.php file if this file is loaded from its dumped location,
|
||||
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||
self::$installed = require __DIR__ . '/installed.php';
|
||||
} else {
|
||||
self::$installed = array();
|
||||
}
|
||||
}
|
||||
$installed[] = self::$installed;
|
||||
|
||||
return $installed;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -17,3 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'andreskrey\\Readability\\' => array($vendorDir . '/fivefilters/readability.php/src'),
|
||||
'fivefilters\\Readability\\' => array($vendorDir . '/fivefilters/readability.php/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
||||
'Masterminds\\' => array($vendorDir . '/masterminds/html5/src'),
|
||||
'League\\Uri\\' => array($vendorDir . '/league/uri-interfaces/src', $vendorDir . '/league/uri/src'),
|
||||
);
|
||||
|
|
|
@ -22,8 +22,6 @@ class ComposerAutoloaderInitb44cc79a0eaef9cd9c2f2ac697cbe9c0
|
|||
return self::$loader;
|
||||
}
|
||||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInitb44cc79a0eaef9cd9c2f2ac697cbe9c0', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitb44cc79a0eaef9cd9c2f2ac697cbe9c0', 'loadClassLoader'));
|
||||
|
|
|
@ -7,18 +7,27 @@ namespace Composer\Autoload;
|
|||
class ComposerStaticInitb44cc79a0eaef9cd9c2f2ac697cbe9c0
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'a' =>
|
||||
'f' =>
|
||||
array (
|
||||
'andreskrey\\Readability\\' => 23,
|
||||
'fivefilters\\Readability\\' => 24,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
),
|
||||
'M' =>
|
||||
array (
|
||||
'Masterminds\\' => 12,
|
||||
),
|
||||
'L' =>
|
||||
array (
|
||||
'League\\Uri\\' => 11,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'andreskrey\\Readability\\' =>
|
||||
'fivefilters\\Readability\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/fivefilters/readability.php/src',
|
||||
),
|
||||
|
@ -26,6 +35,19 @@ class ComposerStaticInitb44cc79a0eaef9cd9c2f2ac697cbe9c0
|
|||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||
),
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
),
|
||||
'Masterminds\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/masterminds/html5/src',
|
||||
),
|
||||
'League\\Uri\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/uri-interfaces/src',
|
||||
1 => __DIR__ . '/..' . '/league/uri/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
|
|
|
@ -2,42 +2,43 @@
|
|||
"packages": [
|
||||
{
|
||||
"name": "fivefilters/readability.php",
|
||||
"version": "v2.1.0",
|
||||
"version_normalized": "2.1.0.0",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fivefilters/readability.php.git",
|
||||
"reference": "7617a912b6c527909168f5d41d263792f171c42a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fivefilters/readability.php/zipball/7617a912b6c527909168f5d41d263792f171c42a",
|
||||
"reference": "7617a912b6c527909168f5d41d263792f171c42a",
|
||||
"shasum": ""
|
||||
"url": "https://dev.tt-rss.org/fox/readability-php.git",
|
||||
"reference": "5ad152c70376002f043bb936d8ae5eed103fb993"
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"php": ">=7.0.0",
|
||||
"league/uri": "^6.4",
|
||||
"masterminds/html5": "^2.0",
|
||||
"php": ">=7.3.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"monolog/monolog": "^1.24",
|
||||
"phpunit/phpunit": "^6.5"
|
||||
"monolog/monolog": "^2.3",
|
||||
"phpunit/phpunit": "^9"
|
||||
},
|
||||
"suggest": {
|
||||
"monolog/monolog": "Allow logging debug information"
|
||||
},
|
||||
"time": "2019-07-22T21:42:25+00:00",
|
||||
"time": "2022-07-16T13:23:08+00:00",
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"installation-source": "source",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"andreskrey\\Readability\\": "src/"
|
||||
"fivefilters\\Readability\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"fivefilters\\Readability\\Test\\": "test"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
|
@ -45,20 +46,327 @@
|
|||
{
|
||||
"name": "Andres Rey",
|
||||
"email": "andreskrey@gmail.com",
|
||||
"role": "Lead Developer"
|
||||
"role": "Original Developer"
|
||||
},
|
||||
{
|
||||
"name": "Keyvan Minoukadeh",
|
||||
"email": "keyvan@fivefilters.org",
|
||||
"homepage": "https://www.fivefilters.org",
|
||||
"role": "Developer/Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "A PHP port of Readability.js",
|
||||
"homepage": "https://github.com/andreskrey/readability",
|
||||
"homepage": "https://github.com/fivefilters/readability.php",
|
||||
"keywords": [
|
||||
"html",
|
||||
"readability"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/fivefilters/readability.php/tree/v2.1.0"
|
||||
},
|
||||
"install-path": "../fivefilters/readability.php"
|
||||
},
|
||||
{
|
||||
"name": "league/uri",
|
||||
"version": "6.7.1",
|
||||
"version_normalized": "6.7.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri.git",
|
||||
"reference": "2d7c87a0860f3126a39f44a8a9bf2fed402dcfea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/2d7c87a0860f3126a39f44a8a9bf2fed402dcfea",
|
||||
"reference": "2d7c87a0860f3126a39f44a8a9bf2fed402dcfea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"league/uri-interfaces": "^2.3",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"league/uri-schemes": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^v3.3.2",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"php-http/psr7-integration-tests": "^1.1",
|
||||
"phpstan/phpstan": "^1.2.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.1.0",
|
||||
"phpunit/phpunit": "^9.5.10",
|
||||
"psr/http-factory": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-fileinfo": "Needed to create Data URI from a filepath",
|
||||
"ext-intl": "Needed to improve host validation",
|
||||
"league/uri-components": "Needed to easily manipulate URI objects",
|
||||
"psr/http-factory": "Needed to use the URI factory"
|
||||
},
|
||||
"time": "2022-06-29T09:48:18+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Uri\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ignace Nyamagana Butera",
|
||||
"email": "nyamsprod@gmail.com",
|
||||
"homepage": "https://nyamsprod.com"
|
||||
}
|
||||
],
|
||||
"description": "URI manipulation library",
|
||||
"homepage": "https://uri.thephpleague.com",
|
||||
"keywords": [
|
||||
"data-uri",
|
||||
"file-uri",
|
||||
"ftp",
|
||||
"hostname",
|
||||
"http",
|
||||
"https",
|
||||
"middleware",
|
||||
"parse_str",
|
||||
"parse_url",
|
||||
"psr-7",
|
||||
"query-string",
|
||||
"querystring",
|
||||
"rfc3986",
|
||||
"rfc3987",
|
||||
"rfc6570",
|
||||
"uri",
|
||||
"uri-template",
|
||||
"url",
|
||||
"ws"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri/issues",
|
||||
"source": "https://github.com/thephpleague/uri/tree/6.7.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/nyamsprod",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../league/uri"
|
||||
},
|
||||
{
|
||||
"name": "league/uri-interfaces",
|
||||
"version": "2.3.0",
|
||||
"version_normalized": "2.3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri-interfaces.git",
|
||||
"reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
|
||||
"reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.19",
|
||||
"phpstan/phpstan": "^0.12.90",
|
||||
"phpstan/phpstan-phpunit": "^0.12.19",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.9",
|
||||
"phpunit/phpunit": "^8.5.15 || ^9.5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "to use the IDNA feature",
|
||||
"symfony/intl": "to use the IDNA feature via Symfony Polyfill"
|
||||
},
|
||||
"time": "2021-06-28T04:27:21+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Uri\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ignace Nyamagana Butera",
|
||||
"email": "nyamsprod@gmail.com",
|
||||
"homepage": "https://nyamsprod.com"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for URI representation",
|
||||
"homepage": "http://github.com/thephpleague/uri-interfaces",
|
||||
"keywords": [
|
||||
"rfc3986",
|
||||
"rfc3987",
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/uri-interfaces/issues",
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/nyamsprod",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../league/uri-interfaces"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.7.5",
|
||||
"version_normalized": "2.7.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "f640ac1bdddff06ea333a920c95bbad8872429ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f640ac1bdddff06ea333a920c95bbad8872429ab",
|
||||
"reference": "f640ac1bdddff06ea333a920c95bbad8872429ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7"
|
||||
},
|
||||
"time": "2021-07-01T14:25:37+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Masterminds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"keywords": [
|
||||
"HTML5",
|
||||
"dom",
|
||||
"html",
|
||||
"parser",
|
||||
"querypath",
|
||||
"serializer",
|
||||
"xml"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.7.5"
|
||||
},
|
||||
"install-path": "../masterminds/html5"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"version_normalized": "1.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2016-08-06T14:39:51+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/master"
|
||||
},
|
||||
"install-path": "../psr/http-message"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
|
|
|
@ -1,42 +1,79 @@
|
|||
<?php return array(
|
||||
'root' =>
|
||||
array (
|
||||
'root' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'reference' => 'a73e3bec45c5523910c711cf882976b71781ac9e',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'fdd1c43612011060b4b876db438eb7ec62dd077d',
|
||||
'name' => '__root__',
|
||||
'dev' => true,
|
||||
),
|
||||
'versions' =>
|
||||
array (
|
||||
'__root__' =>
|
||||
array (
|
||||
'versions' => array(
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'aliases' =>
|
||||
array (
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => 'fdd1c43612011060b4b876db438eb7ec62dd077d',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'reference' => 'a73e3bec45c5523910c711cf882976b71781ac9e',
|
||||
'fivefilters/readability.php' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../fivefilters/readability.php',
|
||||
'aliases' => array(
|
||||
0 => '9999999-dev',
|
||||
),
|
||||
'fivefilters/readability.php' =>
|
||||
array (
|
||||
'pretty_version' => 'v2.1.0',
|
||||
'version' => '2.1.0.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
'reference' => '5ad152c70376002f043bb936d8ae5eed103fb993',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'reference' => '7617a912b6c527909168f5d41d263792f171c42a',
|
||||
'league/uri' => array(
|
||||
'pretty_version' => '6.7.1',
|
||||
'version' => '6.7.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/uri',
|
||||
'aliases' => array(),
|
||||
'reference' => '2d7c87a0860f3126a39f44a8a9bf2fed402dcfea',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log' =>
|
||||
array (
|
||||
'league/uri-interfaces' => array(
|
||||
'pretty_version' => '2.3.0',
|
||||
'version' => '2.3.0.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/uri-interfaces',
|
||||
'aliases' => array(),
|
||||
'reference' => '00e7e2943f76d8cb50c7dfdc2f6dee356e15e383',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'masterminds/html5' => array(
|
||||
'pretty_version' => '2.7.5',
|
||||
'version' => '2.7.5.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../masterminds/html5',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f640ac1bdddff06ea333a920c95bbad8872429ab',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-message',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
'aliases' =>
|
||||
array (
|
||||
),
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/log',
|
||||
'aliases' => array(),
|
||||
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
// platform_check.php @generated by Composer
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 70000)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||
} elseif (!headers_sent()) {
|
||||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
coverage_clover: test/clover.xml
|
||||
json_path: test/coveralls-upload.json
|
||||
service_name: travis-ci
|
|
@ -1 +1,2 @@
|
|||
test/* linguist-language=PHP
|
||||
* text=auto eol=lf
|
|
@ -2,3 +2,4 @@
|
|||
vendor
|
||||
composer.lock
|
||||
/test.*
|
||||
/test/changed/
|
|
@ -1,13 +0,0 @@
|
|||
preset: recommended
|
||||
|
||||
enabled:
|
||||
- concat_with_spaces
|
||||
- unalign_double_arrow
|
||||
|
||||
disabled:
|
||||
- concat_without_spaces
|
||||
- align_double_arrow
|
||||
- simplified_null_return
|
||||
- cast_spaces
|
||||
- trailing_comma_in_multiline_array
|
||||
- phpdoc_align
|
|
@ -1,48 +0,0 @@
|
|||
language: bash
|
||||
services: docker
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- PHP_VERSION=7.3 LIBXML_VERSION=2.9.9
|
||||
- PHP_VERSION=7.3 LIBXML_VERSION=2.9.8
|
||||
- PHP_VERSION=7.3 LIBXML_VERSION=2.9.7
|
||||
- PHP_VERSION=7.3 LIBXML_VERSION=2.9.6
|
||||
- PHP_VERSION=7.3 LIBXML_VERSION=2.9.5
|
||||
- PHP_VERSION=7.3 LIBXML_VERSION=2.9.4
|
||||
- PHP_VERSION=7.2 LIBXML_VERSION=2.9.9
|
||||
- PHP_VERSION=7.2 LIBXML_VERSION=2.9.8
|
||||
- PHP_VERSION=7.2 LIBXML_VERSION=2.9.7
|
||||
- PHP_VERSION=7.2 LIBXML_VERSION=2.9.6
|
||||
- PHP_VERSION=7.2 LIBXML_VERSION=2.9.5
|
||||
- PHP_VERSION=7.2 LIBXML_VERSION=2.9.4
|
||||
- PHP_VERSION=7.1 LIBXML_VERSION=2.9.9
|
||||
- PHP_VERSION=7.1 LIBXML_VERSION=2.9.8
|
||||
- PHP_VERSION=7.1 LIBXML_VERSION=2.9.7
|
||||
- PHP_VERSION=7.1 LIBXML_VERSION=2.9.6
|
||||
- PHP_VERSION=7.1 LIBXML_VERSION=2.9.5
|
||||
- PHP_VERSION=7.1 LIBXML_VERSION=2.9.4
|
||||
- PHP_VERSION=7.0 LIBXML_VERSION=2.9.9
|
||||
- PHP_VERSION=7.0 LIBXML_VERSION=2.9.8
|
||||
- PHP_VERSION=7.0 LIBXML_VERSION=2.9.7
|
||||
- PHP_VERSION=7.0 LIBXML_VERSION=2.9.6
|
||||
- PHP_VERSION=7.0 LIBXML_VERSION=2.9.5
|
||||
- PHP_VERSION=7.0 LIBXML_VERSION=2.9.4
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: LIBXML_VERSION=2.9.9
|
||||
- env: LIBXML_VERSION=2.9.8
|
||||
- env: LIBXML_VERSION=2.9.7
|
||||
- env: LIBXML_VERSION=2.9.6
|
||||
- env: LIBXML_VERSION=2.9.5
|
||||
|
||||
install:
|
||||
- docker run --rm --volume $PWD:/app --workdir="/app" composer install
|
||||
|
||||
script:
|
||||
- docker build --build-arg PHP_VERSION=${PHP_VERSION} --build-arg LIBXML_VERSION=${LIBXML_VERSION} -t travis-build - < ./docker/php/Dockerfile
|
||||
- docker run --volume $PWD:/app --workdir="/app" travis-build php ./vendor/bin/phpunit --coverage-clover /app/test/clover.xml
|
||||
|
||||
after_script:
|
||||
- docker run --volume $PWD:/app --workdir="/app" composer require php-coveralls/php-coveralls:^2.0
|
||||
- docker run --volume $PWD:/app --workdir="/app" --env TRAVIS=${TRAVIS} --env TRAVIS_JOB_ID=${TRAVIS_JOB_ID} travis-build php ./vendor/php-coveralls/php-coveralls/bin/php-coveralls -v
|
|
@ -11,3 +11,4 @@ The AUTHORS/Contributors are (and/or have been):
|
|||
* Sergiy Lavryk
|
||||
* Pedro Amorim
|
||||
* Malu Decks
|
||||
* Keyvan Minoukadeh
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
Contributions are **welcome** and will be fully **credited**.
|
||||
|
||||
We accept contributions via Pull Requests on [Github](https://github.com/andreskrey/readability.php/).
|
||||
When it comes to the core article-extraction functionality, please contribute to [Mozilla's Readability](https://github.com/mozilla/readability/) repository, as we're trying to mirror that here.
|
||||
|
||||
For anything else, we accept contributions via Pull Requests on [Github](https://github.com/fivefilters/readability.php/).
|
||||
|
||||
## Pull Requests
|
||||
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
.PHONY: test-all
|
||||
|
||||
test-all: start test-7.3 test-7.2 test-7.1 test-7.0 stop
|
||||
test-all: start test-7.3 test-7.4 test-8 stop
|
||||
|
||||
test-7.3:
|
||||
docker-compose exec php-7.3-libxml-2.9.9 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
docker-compose exec php-7.3-libxml-2.9.10 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
|
||||
test-7.2:
|
||||
docker-compose exec php-7.2-libxml-2.9.9 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
test-7.4:
|
||||
docker-compose exec php-7.4-libxml-2.9.10 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
|
||||
test-7.1:
|
||||
docker-compose exec php-7.1-libxml-2.9.9 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
|
||||
test-7.0:
|
||||
docker-compose exec php-7.0-libxml-2.9.9 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
test-8:
|
||||
docker-compose exec php-8-libxml-2.9.10 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
|
||||
start:
|
||||
docker-compose up -d php-7.3-libxml-2.9.9 php-7.2-libxml-2.9.9 php-7.1-libxml-2.9.9 php-7.0-libxml-2.9.9
|
||||
docker-compose up -d php-7.3-libxml-2.9.10 php-7.4-libxml-2.9.10 php-8-libxml-2.9.10
|
||||
|
||||
stop:
|
||||
docker-compose stop
|
||||
|
||||
test-all-versions:
|
||||
for php_version in 7.0 7.1 7.2 7.3; do \
|
||||
for libxml_version in 2.9.4 2.9.5 2.9.6 2.9.7 2.9.8 2.9.9; do \
|
||||
for php_version in 7.3 7.4 8; do \
|
||||
for libxml_version in 2.9.4 2.9.5 2.9.10 2.9.12; do \
|
||||
docker-compose up -d php-$$php_version-libxml-$$libxml_version; \
|
||||
docker-compose exec php-$$php_version-libxml-$$libxml_version php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml; \
|
||||
done \
|
||||
|
|
|
@ -1,32 +1,51 @@
|
|||
# Readability.php
|
||||
[![Latest Stable Version](https://poser.pugx.org/andreskrey/readability.php/v/stable)](https://packagist.org/packages/andreskrey/readability.php) [![Build Status](https://travis-ci.org/andreskrey/readability.php.svg?branch=master)](https://travis-ci.org/andreskrey/readability.php) [![Coverage Status](https://coveralls.io/repos/github/andreskrey/readability.php/badge.svg?branch=master)](https://coveralls.io/github/andreskrey/readability.php/?branch=master) [![StyleCI](https://styleci.io/repos/71042668/shield?branch=master)](https://styleci.io/repos/71042668) [![Total Downloads](https://poser.pugx.org/andreskrey/readability.php/downloads)](https://packagist.org/packages/andreskrey/readability.php) [![Monthly Downloads](https://poser.pugx.org/andreskrey/readability.php/d/monthly)](https://packagist.org/packages/andreskrey/readability.php)
|
||||
|
||||
## News (August 2021)
|
||||
|
||||
Andres Rey, the [original developer](https://github.com/andreskrey/readability.php) of Readability.php has kindly let us take over maintenance and development of the project.
|
||||
|
||||
Please bear with us while we catch up with [Readability.js](https://github.com/mozilla/readability) changes. There'll be a new release (3.0.0) when we're ready.
|
||||
|
||||
For the changes we've made so far in this repository, please see our [blog post](https://www.fivefilters.org/2021/readability/).
|
||||
|
||||
## About
|
||||
|
||||
[![Latest Stable Version](https://poser.pugx.org/fivefilters/readability.php/v/stable)](https://packagist.org/packages/fivefilters/readability.php) [![Tests](https://github.com/fivefilters/readability.php/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/fivefilters/readability.php/actions/workflows/main.yml)
|
||||
|
||||
PHP port of *Mozilla's* **[Readability.js](https://github.com/mozilla/readability)**. Parses html text (usually news and other articles) and returns **title**, **author**, **main image** and **text content** without nav bars, ads, footers, or anything that isn't the main body of the text. Analyzes each node, gives them a score, and determines what's relevant and what can be discarded.
|
||||
|
||||
![Screenshot](https://raw.githubusercontent.com/andreskrey/readability.php/assets/screenshot.png)
|
||||
![Screenshot](https://raw.githubusercontent.com/fivefilters/readability.php/assets/screenshot.png)
|
||||
|
||||
The project aim is to be a 1 to 1 port of Mozilla's version and to follow closely all changes introduced there, but there are some major differences on the structure. Most of the code is a 1:1 copy –even the comments were imported– but some functions and structures were adapted to suit better the PHP language.
|
||||
|
||||
**Lead Developer**: Andres Rey
|
||||
**Original Developer**: Andres Rey
|
||||
|
||||
**Developer/Maintainer**: FiveFilters.org
|
||||
|
||||
## Code porting
|
||||
|
||||
Master branch - Up to date on 26 August 2021, with the exception of a [piece of code](https://github.com/fivefilters/readability.php/commit/1c662465bded2ab3acf3b975a1315c8c45f0bf73#diff-b9b31807b1a39caec18ddc293e9c52931ba8b55191c61e6b77a623d699a599ffR1899) which doesn't produce the same results in PHP for us compard to the JS version. Perhaps there's an error, or some difference in the underlying code that affects this. If you know what's wrong, please feel free to drop us a note or submit a pull request. :)
|
||||
|
||||
Version 2.1.0 - Up to date with Readability.js up to [19 Nov 2018](https://github.com/mozilla/readability/commit/876c81f710711ba2afb36dd83889d4c5b4fc2743).
|
||||
|
||||
## Requirements
|
||||
|
||||
PHP 7.0+, ext-dom, ext-xml, and ext-mbstring. To install all this dependencies (in the rare case your system does not have them already), you could try something like this in *nix like environments:
|
||||
PHP 7.3+, ext-dom, ext-xml, and ext-mbstring. To install these dependencies (in the rare case your system does not have them already), you could try something like this in *nix like environments:
|
||||
|
||||
`$ sudo apt-get install php7.1-xml php7.1-mbstring`
|
||||
`$ sudo apt-get install php7.4-xml php7.4-mbstring`
|
||||
|
||||
## How to use it
|
||||
|
||||
First you have to require the library using composer:
|
||||
|
||||
`composer require andreskrey/readability.php`
|
||||
`composer require fivefilters/readability.php`
|
||||
|
||||
Then, create a Readability class and pass a Configuration class, feed the `parse()` function with your HTML and echo the variable:
|
||||
|
||||
```php
|
||||
use andreskrey\Readability\Readability;
|
||||
use andreskrey\Readability\Configuration;
|
||||
use andreskrey\Readability\ParseException;
|
||||
use fivefilters\Readability\Readability;
|
||||
use fivefilters\Readability\Configuration;
|
||||
use fivefilters\Readability\ParseException;
|
||||
|
||||
$readability = new Readability(new Configuration());
|
||||
|
||||
|
@ -86,7 +105,7 @@ $configuration = new Configuration([
|
|||
Then you pass this Configuration object to Readability. The following options are available. Remember to prepend `set` when calling them using native setters.
|
||||
|
||||
- **MaxTopCandidates**: default value `5`, max amount of top level candidates.
|
||||
- **WordThreshold**: default value `500`, minimum amount of characters to consider that the article was parsed successful.
|
||||
- **CharThreshold**: default value `500`, minimum amount of characters to consider that the article was parsed successful.
|
||||
- **ArticleByLine**: default value `false`, search for the article byline and remove it from the text. It will be moved to the article metadata.
|
||||
- **StripUnlikelyCandidates**: default value `true`, remove nodes that are unlikely to have relevant information. Useful for debugging or parsing complex or non-standard articles.
|
||||
- **CleanConditionally**: default value `true`, remove certain nodes after parsing to return a cleaner result.
|
||||
|
@ -95,13 +114,15 @@ Then you pass this Configuration object to Readability. The following options ar
|
|||
- **SubstituteEntities**: default value `false`, disables the `substituteEntities` flag of libxml. Will avoid substituting HTML entities. Like `á` to á.
|
||||
- **NormalizeEntities**: default value `false`, converts UTF-8 characters to its HTML Entity equivalent. Useful to parse HTML with mixed encoding.
|
||||
- **OriginalURL**: default value `http://fakehost`, original URL from the article used to fix relative URLs.
|
||||
- **SummonCthulhu**: default value `false`, remove all `<script>` nodes via regex. This is not ideal as it might break things, but might be the only solution to [libxml problems with unescaped javascript](https://github.com/andreskrey/readability.php#known-issues). If you're not parsing Javascript tutorials, it's recommended to always set this option as `true`.
|
||||
- **KeepClasses**: default value `false`, which removes all `class="..."` attribute values from HTML elements.
|
||||
- **Parser**: default value `html5`, which uses HTML5-PHP for parsing. Set to `libxml` to use that instead (not recommended for modern HTML documents).
|
||||
- **SummonCthulhu**: default value `false`, remove all `<script>` nodes via regex. This is not ideal as it might break things, but if you've set the parser to libxml (see above), it might be the only solution to [libxml problems with unescaped javascript](https://github.com/fivefilters/readability.php#known-libxml-parsing-issues).
|
||||
|
||||
### Debug log
|
||||
|
||||
Logging is optional and you will have to inject your own logger to save all the debugging messages. To do so, use a logger that implements the [PSR-3 logging interface](https://github.com/php-fig/log) and pass it to the configuration object. For example:
|
||||
|
||||
```
|
||||
```php
|
||||
// Using monolog
|
||||
|
||||
$log = new Logger('Readability');
|
||||
|
@ -116,7 +137,9 @@ In the log you will find information about the parsed nodes, why they were remov
|
|||
|
||||
Of course the main limitation is PHP. Websites that load the content through lazy loading, AJAX, or any type of javascript fueled call will be ignored (actually, *not ran*) and the resulting text will be incorrect, compared to the readability.js results. All the articles you want to parse with readability.php need to be complete and all the content should be in the HTML already.
|
||||
|
||||
## Known Issues
|
||||
## Known libxml parsing issues
|
||||
|
||||
Readability.php as of version 3.0.0 uses a HTML5 parser. Earlier versions used libxml. The issues below apply to libxml parsing, so if you're using an earlier version of Readability.php (pre 3.0.0), or if you've set the parser to libxml in the configuration, read on...
|
||||
|
||||
### Javascript spilling into the text body
|
||||
|
||||
|
@ -153,7 +176,11 @@ Self closing tags like `<br />` get automatically expanded to `<br></br`. No way
|
|||
|
||||
## Dependencies
|
||||
|
||||
Readability.php uses the [PSR Log](https://github.com/php-fig/log) interface to define the allowed type of loggers. [Monolog](https://github.com/Seldaek/monolog) is only required on development installations. (`--dev` option during `composer install`).
|
||||
Readability.php uses
|
||||
|
||||
* [HTML5-PHP](https://github.com/Masterminds/html5-php) to parse and serialise HTML.
|
||||
* [PSR Log](https://github.com/php-fig/log) interface to define the allowed type of loggers.
|
||||
* [Monolog](https://github.com/Seldaek/monolog) is only required on development installations. (`--dev` option during `composer install`).
|
||||
|
||||
## To-do
|
||||
|
||||
|
@ -165,21 +192,44 @@ Readability.php uses the [PSR Log](https://github.com/php-fig/log) interface to
|
|||
|
||||
Readability parses all the text with DOMDocument, scans the text nodes and gives the a score, based on the amount of words, links and type of element. Then it selects the highest scoring element and creates a new DOMDocument with all its siblings. Each sibling is scored to discard useless elements, like nav bars, empty nodes, etc.
|
||||
|
||||
## Security
|
||||
|
||||
If you're going to use Readability with untrusted input (whether in HTML or DOM form), we **strongly** recommend you use a sanitizer library like [HTML Purifier](https://github.com/ezyang/htmlpurifier) to avoid script injection when you use
|
||||
the output of Readability. We would also recommend using [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) to add further defense-in-depth
|
||||
restrictions to what you allow the resulting content to do. The Firefox integration of
|
||||
reader mode uses both of these techniques itself. Sanitizing unsafe content out of the input is explicitly not something we aim to do as part of Readability itself - there are other good sanitizer libraries out there, use them!
|
||||
|
||||
## Testing
|
||||
|
||||
Any version of PHP installed locally should be enough to develop new features and add new test cases. If you want to be 100% sure that your change doesn't create any issues with other versions of PHP, you can use the provided Docker containers to test currently in 7.0, 7.1, and 7.2.
|
||||
Any version of PHP from 7.3 and above installed locally should be enough to develop new features and add new test cases. If you want to be 100% sure that your change doesn't create any issues with other versions of PHP, you can use the provided Docker containers to test currently in 7.3, 7.4, and 8.0.
|
||||
|
||||
You'll need Docker and Docker Compose for this. To run all the tests in all the available versions just type the following command:
|
||||
You'll need Docker and Docker Compose for this. To run all the tests in the three PHP versions above, just type the following command:
|
||||
|
||||
```bash
|
||||
make test-all
|
||||
```
|
||||
|
||||
This will start all the containers and run all the tests on every supported version of PHP. If you want to test against a specific version, you can use `make test-7.0`, `make test-7.1`, or `make test-7.2`.
|
||||
This will start all the containers and run all the tests on every supported version of PHP. If you want to test against a specific version, you can use `make test-7.3`, `make test-7.4`, or `make test-8`.
|
||||
|
||||
## Code porting
|
||||
### Different versions of libxml
|
||||
|
||||
Up to date with readability.js as of [19 Nov 2018](https://github.com/mozilla/readability/commit/876c81f710711ba2afb36dd83889d4c5b4fc2743).
|
||||
If you want to test against supported versions of PHP *AND* multiple versions of libxml, run `test-all-versions`. This will test against PHP versions 7.3 to 8 and libxml versions 2.9.4, 2.9.5, 2.9.10, and 2.9.12. Normally you won't need to do this unless you think you've found a bug on an specific version of libxml.
|
||||
|
||||
### Updating the expected tests
|
||||
|
||||
If you've made an improvement to the code, you'll probably want to examine the Readability.php output for the test cases here. To do that, run the following command first from the root of the project folder:
|
||||
|
||||
docker-compose up -d php-7.4-libxml-2.9.10
|
||||
|
||||
You should now have a docker image running with the project root folder mapped to /app/ on your Docker instance (see `docker-compose.yml`). Any changes to these files will be accessible from the Docker instance from now on.
|
||||
|
||||
Next, create a folder in tests/ called /changed, then run the following command to run the test suite:
|
||||
|
||||
docker-compose exec -e output-changes=1 -e output-diff=1 php-7.4-libxml-2.9.10 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml
|
||||
|
||||
The two environment variables (`output-changes=1` and `output-diff=1`) will result in new output for any failing test (along with a diff of changes) being written to the changed/ folder.
|
||||
|
||||
If you're happy the changes are okay, set `output-diff=0` and the diff files will no longer be written, making it easier to copy the new expected output files over to their corresponding locations in test-pages\.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -1,35 +1,43 @@
|
|||
{
|
||||
"name": "andreskrey/readability.php",
|
||||
"name": "fivefilters/readability.php",
|
||||
"type": "library",
|
||||
"description": "A PHP port of Readability.js",
|
||||
"keywords": ["readability", "html"],
|
||||
"homepage": "https://github.com/andreskrey/readability",
|
||||
"homepage": "https://github.com/fivefilters/readability.php",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andres Rey",
|
||||
"email": "andreskrey@gmail.com",
|
||||
"role": "Lead Developer"
|
||||
"role": "Original Developer"
|
||||
},
|
||||
{
|
||||
"name": "Keyvan Minoukadeh",
|
||||
"email": "keyvan@fivefilters.org",
|
||||
"homepage": "https://www.fivefilters.org",
|
||||
"role": "Developer/Maintainer"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"andreskrey\\Readability\\": "src/"
|
||||
"fivefilters\\Readability\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {"andreskrey\\Readability\\Test\\": "test"}
|
||||
"psr-4": {"fivefilters\\Readability\\Test\\": "test"}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"php": ">=7.3.0",
|
||||
"ext-dom": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"psr/log": "^1.0"
|
||||
"psr/log": "^1.0",
|
||||
"masterminds/html5": "^2.0",
|
||||
"league/uri": "^6.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.5",
|
||||
"monolog/monolog": "^1.24"
|
||||
"phpunit/phpunit": "^9",
|
||||
"monolog/monolog": "^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"monolog/monolog": "Allow logging debug information"
|
||||
|
|
|
@ -1,159 +1,15 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
php-7.0-libxml-2.9.4: &template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.4
|
||||
PHP_VERSION: 7.0
|
||||
volumes:
|
||||
- ./:/app
|
||||
tty: true
|
||||
|
||||
php-7.0-libxml-2.9.5:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.5
|
||||
PHP_VERSION: 7.0
|
||||
|
||||
php-7.0-libxml-2.9.6:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.6
|
||||
PHP_VERSION: 7.0
|
||||
|
||||
php-7.0-libxml-2.9.7:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.7
|
||||
PHP_VERSION: 7.0
|
||||
|
||||
php-7.0-libxml-2.9.8:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.8
|
||||
PHP_VERSION: 7.0
|
||||
|
||||
php-7.0-libxml-2.9.9:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.9
|
||||
PHP_VERSION: 7.0
|
||||
|
||||
php-7.1-libxml-2.9.4:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.4
|
||||
PHP_VERSION: 7.1
|
||||
|
||||
php-7.1-libxml-2.9.5:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.5
|
||||
PHP_VERSION: 7.1
|
||||
|
||||
php-7.1-libxml-2.9.6:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.6
|
||||
PHP_VERSION: 7.1
|
||||
|
||||
php-7.1-libxml-2.9.7:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.7
|
||||
PHP_VERSION: 7.1
|
||||
|
||||
php-7.1-libxml-2.9.8:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.8
|
||||
PHP_VERSION: 7.1
|
||||
|
||||
php-7.1-libxml-2.9.9:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.9
|
||||
PHP_VERSION: 7.1
|
||||
|
||||
php-7.2-libxml-2.9.4:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.4
|
||||
PHP_VERSION: 7.2
|
||||
|
||||
php-7.2-libxml-2.9.5:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.5
|
||||
PHP_VERSION: 7.2
|
||||
|
||||
php-7.2-libxml-2.9.6:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.6
|
||||
PHP_VERSION: 7.2
|
||||
|
||||
php-7.2-libxml-2.9.7:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.7
|
||||
PHP_VERSION: 7.2
|
||||
|
||||
php-7.2-libxml-2.9.8:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.8
|
||||
PHP_VERSION: 7.2
|
||||
|
||||
php-7.2-libxml-2.9.9:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.9
|
||||
PHP_VERSION: 7.2
|
||||
|
||||
php-7.3-libxml-2.9.4:
|
||||
<<: *template
|
||||
php-7.3-libxml-2.9.4: &template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.4
|
||||
PHP_VERSION: 7.3
|
||||
volumes:
|
||||
- ./:/app
|
||||
tty: true
|
||||
|
||||
php-7.3-libxml-2.9.5:
|
||||
<<: *template
|
||||
|
@ -163,34 +19,82 @@ services:
|
|||
LIBXML_VERSION: 2.9.5
|
||||
PHP_VERSION: 7.3
|
||||
|
||||
php-7.3-libxml-2.9.6:
|
||||
php-7.3-libxml-2.9.10:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.6
|
||||
LIBXML_VERSION: 2.9.10
|
||||
PHP_VERSION: 7.3
|
||||
|
||||
php-7.3-libxml-2.9.7:
|
||||
php-7.3-libxml-2.9.12:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.7
|
||||
LIBXML_VERSION: 2.9.12
|
||||
PHP_VERSION: 7.3
|
||||
|
||||
php-7.3-libxml-2.9.8:
|
||||
php-7.4-libxml-2.9.4:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.8
|
||||
PHP_VERSION: 7.3
|
||||
LIBXML_VERSION: 2.9.4
|
||||
PHP_VERSION: 7.4
|
||||
|
||||
php-7.3-libxml-2.9.9:
|
||||
php-7.4-libxml-2.9.5:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.9
|
||||
PHP_VERSION: 7.3
|
||||
LIBXML_VERSION: 2.9.5
|
||||
PHP_VERSION: 7.4
|
||||
|
||||
php-7.4-libxml-2.9.10:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.10
|
||||
PHP_VERSION: 7.4
|
||||
|
||||
php-7.4-libxml-2.9.12:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.12
|
||||
PHP_VERSION: 7.4
|
||||
|
||||
php-8-libxml-2.9.4:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.4
|
||||
PHP_VERSION: 8
|
||||
|
||||
php-8-libxml-2.9.5:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.5
|
||||
PHP_VERSION: 8
|
||||
|
||||
php-8-libxml-2.9.10:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.10
|
||||
PHP_VERSION: 8
|
||||
|
||||
php-8-libxml-2.9.12:
|
||||
<<: *template
|
||||
build:
|
||||
context: ./docker/php
|
||||
args:
|
||||
LIBXML_VERSION: 2.9.12
|
||||
PHP_VERSION: 8
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
# Load pre-built image of PHP (php-cli) and libxml.
|
||||
# See https://hub.docker.com/r/fivefilters/php-libxml for supported versions
|
||||
# Use build.Dockerfile to compile new versions of PHP/libxml
|
||||
|
||||
# For reference, default package versions for Ubuntu are:
|
||||
# Ubuntu 18.04 - php 7.2, libxml 2.9.4
|
||||
# Ubuntu 20.04 - php 7.4, libxml 2.9.10
|
||||
# Ubuntu 20.10 - php 7.4, libxml 2.9.10
|
||||
# Ubuntu 21.04 - php 7.4, libxml 2.9.10
|
||||
# Ubuntu 21.10 - php 8.0, libxml 2.9.10
|
||||
|
||||
ARG PHP_VERSION
|
||||
ARG LIBXML_VERSION
|
||||
FROM andreskrey/php-${PHP_VERSION}:libxml-${LIBXML_VERSION}
|
||||
FROM fivefilters/php-libxml:php-${PHP_VERSION}-libxml-${LIBXML_VERSION}
|
||||
|
||||
RUN pecl install xdebug && docker-php-ext-enable xdebug
|
||||
|
||||
# Required by coveralls
|
||||
RUN apt-get install git -y
|
||||
RUN apt-get update
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability;
|
||||
namespace fivefilters\Readability;
|
||||
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -68,6 +68,21 @@ class Configuration
|
|||
*/
|
||||
protected $originalURL = 'http://fakehost';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $parser = 'html5';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $keepClasses = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $disableJSONLD = false;
|
||||
|
||||
/**
|
||||
* Configuration constructor.
|
||||
*
|
||||
|
@ -326,6 +341,66 @@ class Configuration
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getParser()
|
||||
{
|
||||
return $this->parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $parser
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setParser($parser)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getKeepClasses()
|
||||
{
|
||||
return $this->keepClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $keepClasses
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setKeepClasses($keepClasses)
|
||||
{
|
||||
$this->keepClasses = $keepClasses;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getDisableJSONLD()
|
||||
{
|
||||
return $this->disableJSONLD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $disableJSONLD
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDisableJSONLD($disableJSONLD)
|
||||
{
|
||||
$this->disableJSONLD = $disableJSONLD;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMAttr extends \DOMAttr
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMCdataSection extends \DOMCdataSection
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMCharacterData extends \DOMCharacterData
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMComment extends \DOMComment
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMDocument extends \DOMDocument
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMDocumentFragment extends \DOMDocumentFragment
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMDocumentType extends \DOMDocumentType
|
||||
{
|
||||
|
|
|
@ -1,10 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMElement extends \DOMElement
|
||||
{
|
||||
use NodeTrait;
|
||||
|
||||
/**
|
||||
* Returns the child elements of this element.
|
||||
*
|
||||
* To get all child nodes, including non-element nodes like text and comment nodes, use childNodes.
|
||||
*
|
||||
* @return DOMNodeList
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
$newList = new DOMNodeList();
|
||||
foreach ($this->childNodes as $node) {
|
||||
if ($node->nodeType === XML_ELEMENT_NODE) {
|
||||
$newList->add($node);
|
||||
}
|
||||
}
|
||||
return $newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Element immediately prior to the specified one in its parent's children list, or null if the specified element is the first one in the list.
|
||||
*
|
||||
* @see https://wiki.php.net/rfc/dom_living_standard_api
|
||||
* @return DOMElement|null
|
||||
*/
|
||||
public function previousElementSibling()
|
||||
{
|
||||
$previous = $this->previousSibling;
|
||||
while ($previous) {
|
||||
if ($previous->nodeType === XML_ELEMENT_NODE) {
|
||||
return $previous;
|
||||
}
|
||||
$previous = $previous->previousSibling;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMEntity extends \DOMEntity
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMEntityReference extends \DOMEntityReference
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
/**
|
||||
* @method getAttribute($attribute)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
/**
|
||||
* Class DOMNodeList.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMNotation extends \DOMNotation
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMProcessingInstruction extends \DOMProcessingInstruction
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes\DOM;
|
||||
namespace fivefilters\Readability\Nodes\DOM;
|
||||
|
||||
use andreskrey\Readability\Nodes\NodeTrait;
|
||||
use fivefilters\Readability\Nodes\NodeTrait;
|
||||
|
||||
class DOMText extends \DOMText
|
||||
{
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes;
|
||||
namespace fivefilters\Readability\Nodes;
|
||||
|
||||
use andreskrey\Readability\Nodes\DOM\DOMDocument;
|
||||
use andreskrey\Readability\Nodes\DOM\DOMElement;
|
||||
use andreskrey\Readability\Nodes\DOM\DOMNode;
|
||||
use andreskrey\Readability\Nodes\DOM\DOMText;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMDocument;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMElement;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMNode;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMText;
|
||||
use DOMNodeList;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,6 @@ trait NodeTrait
|
|||
* @var array
|
||||
*/
|
||||
private $divToPElements = [
|
||||
'a',
|
||||
'blockquote',
|
||||
'dl',
|
||||
'div',
|
||||
|
@ -47,8 +46,7 @@ trait NodeTrait
|
|||
'p',
|
||||
'pre',
|
||||
'table',
|
||||
'ul',
|
||||
'select',
|
||||
'ul'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -169,6 +167,7 @@ trait NodeTrait
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getAttribute($attributeName)
|
||||
{
|
||||
if (!is_null($this->attributes)) {
|
||||
|
@ -187,6 +186,7 @@ trait NodeTrait
|
|||
*
|
||||
* @see getAttribute
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function hasAttribute($attributeName)
|
||||
{
|
||||
if (!is_null($this->attributes)) {
|
||||
|
@ -240,19 +240,21 @@ trait NodeTrait
|
|||
*/
|
||||
public function getLinkDensity()
|
||||
{
|
||||
$linkLength = 0;
|
||||
$textLength = mb_strlen($this->getTextContent(true));
|
||||
|
||||
if (!$textLength) {
|
||||
if ($textLength === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$linkLength = 0;
|
||||
|
||||
$links = $this->getAllLinks();
|
||||
|
||||
if ($links) {
|
||||
/** @var DOMElement $link */
|
||||
foreach ($links as $link) {
|
||||
$linkLength += mb_strlen($link->getTextContent(true));
|
||||
$href = $link->getAttribute('href');
|
||||
$coefficient = ($href && preg_match(NodeUtility::$regexps['hashUrl'], $href)) ? 0.3 : 1;
|
||||
$linkLength += mb_strlen($link->getTextContent(true)) * $coefficient;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +284,7 @@ trait NodeTrait
|
|||
|
||||
// Look for a special ID
|
||||
$id = $this->getAttribute('id');
|
||||
if (trim($id)) {
|
||||
if (trim($id) !== '') {
|
||||
if (preg_match(NodeUtility::$regexps['negative'], $id)) {
|
||||
$weight -= 25;
|
||||
}
|
||||
|
@ -302,40 +304,16 @@ trait NodeTrait
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTextContent($normalize = false)
|
||||
public function getTextContent($normalize = true)
|
||||
{
|
||||
$nodeValue = $this->nodeValue;
|
||||
$nodeValue = trim($this->textContent);
|
||||
if ($normalize) {
|
||||
$nodeValue = trim(preg_replace('/\s{2,}/', ' ', $nodeValue));
|
||||
$nodeValue = preg_replace(NodeUtility::$regexps['normalize'], ' ', $nodeValue);
|
||||
}
|
||||
|
||||
return $nodeValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the children of the current node.
|
||||
*
|
||||
* @param bool $filterEmptyDOMText Filter empty DOMText nodes?
|
||||
*
|
||||
* @deprecated Use NodeUtility::filterTextNodes, function will be removed in version 3.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getChildren($filterEmptyDOMText = false)
|
||||
{
|
||||
@trigger_error('getChildren was replaced with NodeUtility::filterTextNodes and will be removed in version 3.0', E_USER_DEPRECATED);
|
||||
|
||||
$ret = iterator_to_array($this->childNodes);
|
||||
if ($filterEmptyDOMText) {
|
||||
// Array values is used to discard the key order. Needs to be 0 to whatever without skipping any number
|
||||
$ret = array_values(array_filter($ret, function ($node) {
|
||||
return $node->nodeName !== '#text' || mb_strlen(trim($node->nodeValue));
|
||||
}));
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array indicating how many rows and columns this table has.
|
||||
*
|
||||
|
@ -374,7 +352,7 @@ trait NodeTrait
|
|||
*/
|
||||
public function createNode($originalNode, $tagName)
|
||||
{
|
||||
$text = $originalNode->getTextContent();
|
||||
$text = $originalNode->getTextContent(false);
|
||||
$newNode = $originalNode->ownerDocument->createElement($tagName, $text);
|
||||
|
||||
return $newNode;
|
||||
|
@ -433,7 +411,7 @@ trait NodeTrait
|
|||
}
|
||||
|
||||
/* @var DOMNode $child */
|
||||
return !($child->nodeType === XML_TEXT_NODE && !preg_match('/\S$/', $child->getTextContent()));
|
||||
return !($child->nodeType === XML_TEXT_NODE && preg_match(NodeUtility::$regexps['hasContent'], $child->textContent));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -508,13 +486,14 @@ trait NodeTrait
|
|||
* In the original JS project they check if the node has the style display=none, which unfortunately
|
||||
* in our case we have no way of knowing that. So we just check for the attribute hidden or "display: none".
|
||||
*
|
||||
* Might be a good idea to check for classes or other attributes like 'aria-hidden'
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isProbablyVisible()
|
||||
{
|
||||
return !preg_match('/display:( )?none/', $this->getAttribute('style')) && !$this->hasAttribute('hidden');
|
||||
return !preg_match('/display:( )?none/i', $this->getAttribute('style')) &&
|
||||
!$this->hasAttribute('hidden') &&
|
||||
//check for "fallback-image" so that wikimedia math images are displayed
|
||||
(!$this->hasAttribute('aria-hidden') || $this->getAttribute('aria-hidden') !== 'true' || ($this->hasAttribute('class') && strpos($this->getAttribute('class'), 'fallback-image') !== false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Nodes;
|
||||
namespace fivefilters\Readability\Nodes;
|
||||
|
||||
use andreskrey\Readability\Nodes\DOM\DOMDocument;
|
||||
use andreskrey\Readability\Nodes\DOM\DOMElement;
|
||||
use andreskrey\Readability\Nodes\DOM\DOMNode;
|
||||
use andreskrey\Readability\Nodes\DOM\DOMNodeList;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMDocument;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMElement;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMNode;
|
||||
use fivefilters\Readability\Nodes\DOM\DOMNodeList;
|
||||
|
||||
/**
|
||||
* Class NodeUtility.
|
||||
|
@ -18,31 +18,43 @@ class NodeUtility
|
|||
* @var array
|
||||
*/
|
||||
public static $regexps = [
|
||||
'unlikelyCandidates' => '/-ad-|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i',
|
||||
'okMaybeItsACandidate' => '/and|article|body|column|main|shadow/i',
|
||||
'unlikelyCandidates' => '/-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i',
|
||||
'okMaybeItsACandidate' => '/and|article|body|column|content|main|shadow/i',
|
||||
'extraneous' => '/print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single|utility/i',
|
||||
'byline' => '/byline|author|dateline|writtenby|p-author/i',
|
||||
'replaceFonts' => '/<(\/?)font[^>]*>/gi',
|
||||
'replaceFonts' => '/<(\/?)font[^>]*>/i',
|
||||
'normalize' => '/\s{2,}/',
|
||||
'videos' => '/\/\/(www\.)?((dailymotion|youtube|youtube-nocookie|player\.vimeo|v\.qq)\.com|(archive|upload\.wikimedia)\.org|player\.twitch\.tv)/i',
|
||||
'shareElements' => '/(\b|_)(share|sharedaddy)(\b|_)/i',
|
||||
'nextLink' => '/(next|weiter|continue|>([^\|]|$)|»([^\|]|$))/i',
|
||||
'prevLink' => '/(prev|earl|old|new|<|«)/i',
|
||||
'tokenize' => '/\W+/',
|
||||
'whitespace' => '/^\s*$/',
|
||||
'hasContent' => '/\S$/',
|
||||
'positive' => '/article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i',
|
||||
'negative' => '/hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i',
|
||||
'negative' => '/-ad-|hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i',
|
||||
// \x{00A0} is the unicode version of
|
||||
'onlyWhitespace' => '/\x{00A0}|\s+/u'
|
||||
'onlyWhitespace' => '/\x{00A0}|\s+/u',
|
||||
'hashUrl' => '/^#.+/',
|
||||
'srcsetUrl' => '/(\S+)(\s+[\d.]+[xw])?(\s*(?:,|$))/',
|
||||
'b64DataUrl' => '/^data:\s*([^\s;,]+)\s*;\s*base64\s*,/i',
|
||||
// See: https://schema.org/Article
|
||||
'jsonLdArticleTypes' => '/^Article|AdvertiserContentArticle|NewsArticle|AnalysisNewsArticle|AskPublicNewsArticle|BackgroundNewsArticle|OpinionNewsArticle|ReportageNewsArticle|ReviewNewsArticle|Report|SatiricalArticle|ScholarlyArticle|MedicalScholarlyArticle|SocialMediaPosting|BlogPosting|LiveBlogPosting|DiscussionForumPosting|TechArticle|APIReference$/'
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* Finds the next node, starting from the given node, and ignoring
|
||||
* whitespace in between. If the given node is an element, the same node is
|
||||
* returned.
|
||||
*
|
||||
* Imported from the Element class on league\html-to-markdown.
|
||||
*
|
||||
* @param $node
|
||||
*
|
||||
* @return DOMElement
|
||||
* @return DOMNode
|
||||
*/
|
||||
public static function nextElement($node)
|
||||
public static function nextNode($node)
|
||||
{
|
||||
$next = $node;
|
||||
while ($next
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability;
|
||||
namespace fivefilters\Readability;
|
||||
|
||||
class ParseException extends \Exception
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Test;
|
||||
namespace fivefilters\Readability\Test;
|
||||
|
||||
use andreskrey\Readability\Configuration;
|
||||
use fivefilters\Readability\Configuration;
|
||||
use Monolog\Handler\NullHandler;
|
||||
use Monolog\Logger;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Test;
|
||||
namespace fivefilters\Readability\Test;
|
||||
|
||||
use andreskrey\Readability\Configuration;
|
||||
use andreskrey\Readability\ParseException;
|
||||
use andreskrey\Readability\Readability;
|
||||
use fivefilters\Readability\Configuration;
|
||||
use fivefilters\Readability\ParseException;
|
||||
use fivefilters\Readability\Readability;
|
||||
|
||||
/**
|
||||
* Class ReadabilityTest.
|
||||
|
@ -33,7 +33,30 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||
$readability = new Readability($configuration);
|
||||
$readability->parse($testPage->getSourceHTML());
|
||||
|
||||
$this->assertSame($testPage->getExpectedHTML(), $readability->getContent(), 'Parsed text does not match the expected one.');
|
||||
// Let's (crudely) remove whitespace between tags here to simplify comparison.
|
||||
// This isn't used for output.
|
||||
$from = ['/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s', '/> </s'];
|
||||
$to = ['>', '<', '\\1', '><'];
|
||||
$expected_no_whitespace = preg_replace($from, $to, $testPage->getExpectedHTML());
|
||||
$readability_no_whitespace = preg_replace($from, $to, $readability->getContent());
|
||||
|
||||
if (getenv('output-changes') && $expected_no_whitespace !== $readability_no_whitespace) {
|
||||
@mkdir(__DIR__.'/changed/'.$testPage->getSlug());
|
||||
$new_expected = __DIR__.'/changed/'.$testPage->getSlug().'/expected.html';
|
||||
$old_expected = __DIR__.'/test-pages/'.$testPage->getSlug().'/expected.html';
|
||||
//file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/readability.html', $readability_no_whitespace);
|
||||
//file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/expected-current.html', $expected_no_whitespace);
|
||||
file_put_contents($new_expected, $readability->getContent());
|
||||
if (getenv('output-diff')) {
|
||||
file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/diff-expected.txt', shell_exec(sprintf('diff -u -d %s %s', $old_expected, $new_expected)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->assertSame($expected_no_whitespace, $readability_no_whitespace, 'Parsed text does not match the expected one.');
|
||||
|
||||
//$this->assertSame($testPage->getExpectedHTML(), $readability->getContent(), 'Parsed text does not match the expected one.');
|
||||
//$this->assertXmlStringEqualsXmlString($testPage->getExpectedHTML(), $readability->getContent(), 'Parsed text does not match the expected one.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +81,26 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||
$readability = new Readability($configuration);
|
||||
$readability->parse($testPage->getSourceHTML());
|
||||
|
||||
$metadata = [
|
||||
'Author' => $readability->getAuthor(),
|
||||
'Direction' => $readability->getDirection(),
|
||||
'Excerpt' => $readability->getExcerpt(),
|
||||
'Image' => $readability->getImage(),
|
||||
'Title' => $readability->getTitle(),
|
||||
'SiteName' => $readability->getSiteName()
|
||||
];
|
||||
|
||||
if (getenv('output-changes') && (array)$testPage->getExpectedMetadata() !== $metadata) {
|
||||
@mkdir(__DIR__.'/changed/'.$testPage->getSlug());
|
||||
$new_expected = __DIR__.'/changed/'.$testPage->getSlug().'/expected-metadata.json';
|
||||
$old_expected = __DIR__.'/test-pages/'.$testPage->getSlug().'/expected-metadata.json';
|
||||
//file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/expected-metadata-current.json', json_encode($testPage->getExpectedMetadata(), JSON_PRETTY_PRINT));
|
||||
file_put_contents($new_expected, json_encode((object)$metadata, JSON_PRETTY_PRINT));
|
||||
if (getenv('output-diff')) {
|
||||
file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/diff-expected-metadata.txt', shell_exec(sprintf('diff -u -d %s %s', $old_expected, $new_expected)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertSame($testPage->getExpectedMetadata()->Author, $readability->getAuthor(), 'Parsed Author does not match expected value.');
|
||||
$this->assertSame($testPage->getExpectedMetadata()->Direction, $readability->getDirection(), 'Parsed Direction does not match expected value.');
|
||||
$this->assertSame($testPage->getExpectedMetadata()->Excerpt, $readability->getExcerpt(), 'Parsed Excerpt does not match expected value.');
|
||||
|
@ -85,7 +128,18 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||
$readability = new Readability($configuration);
|
||||
$readability->parse($testPage->getSourceHTML());
|
||||
|
||||
$this->assertSame($testPage->getExpectedImages(), $readability->getImages());
|
||||
if (getenv('output-changes') && $testPage->getExpectedImages() !== array_values($readability->getImages())) {
|
||||
@mkdir(__DIR__.'/changed/'.$testPage->getSlug());
|
||||
$new_expected = __DIR__.'/changed/'.$testPage->getSlug().'/expected-images.json';
|
||||
$old_expected = __DIR__.'/test-pages/'.$testPage->getSlug().'/expected-images.json';
|
||||
//file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/expected-images-current.json', json_encode($testPage->getExpectedImages(), JSON_PRETTY_PRINT));
|
||||
file_put_contents($new_expected, json_encode(array_values($readability->getImages()), JSON_PRETTY_PRINT));
|
||||
if (getenv('output-diff')) {
|
||||
file_put_contents(__DIR__.'/changed/'.$testPage->getSlug().'/diff-expected-images.txt', shell_exec(sprintf('diff -u -d %s %s', $old_expected, $new_expected)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertSame($testPage->getExpectedImages(), array_values($readability->getImages()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,13 +155,14 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||
foreach (array_slice($testPages, 2) as $testPage) {
|
||||
$testCasePath = $path . DIRECTORY_SEPARATOR . $testPage . DIRECTORY_SEPARATOR;
|
||||
|
||||
$slug = $testPage;
|
||||
$source = file_get_contents($testCasePath . 'source.html');
|
||||
$expectedHTML = file_get_contents($testCasePath . 'expected.html');
|
||||
$expectedImages = json_decode(file_get_contents($testCasePath . 'expected-images.json'), true);
|
||||
$expectedMetadata = json_decode(file_get_contents($testCasePath . 'expected-metadata.json'));
|
||||
$expectedHTML = file_exists($testCasePath . 'expected.html') ? file_get_contents($testCasePath . 'expected.html') : '';
|
||||
$expectedImages = file_exists($testCasePath . 'expected-images.json') ? json_decode(file_get_contents($testCasePath . 'expected-images.json'), true) : [];
|
||||
$expectedMetadata = file_exists($testCasePath . 'expected-metadata.json') ? json_decode(file_get_contents($testCasePath . 'expected-metadata.json')) : (object)[];
|
||||
$configuration = file_exists($testCasePath . 'config.json') ? json_decode(file_get_contents($testCasePath . 'config.json'), true) : [];
|
||||
|
||||
yield $testPage => [new TestPage($configuration, $source, $expectedHTML, $expectedImages, $expectedMetadata)];
|
||||
yield $testPage => [new TestPage($slug, $configuration, $source, $expectedHTML, $expectedImages, $expectedMetadata)];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace andreskrey\Readability\Test;
|
||||
namespace fivefilters\Readability\Test;
|
||||
|
||||
class TestPage
|
||||
{
|
||||
private $slug;
|
||||
private $configuration;
|
||||
private $sourceHTML;
|
||||
private $expectedHTML;
|
||||
private $expectedImages;
|
||||
private $expectedMetadata;
|
||||
|
||||
public function __construct($configuration, $sourceHTML, $expectedHTML, $expectedImages, $expectedMetadata)
|
||||
public function __construct($slug, $configuration, $sourceHTML, $expectedHTML, $expectedImages, $expectedMetadata)
|
||||
{
|
||||
$this->slug = $slug;
|
||||
$this->configuration = $configuration;
|
||||
$this->sourceHTML = $sourceHTML;
|
||||
$this->expectedHTML = $expectedHTML;
|
||||
|
@ -19,6 +21,14 @@ class TestPage
|
|||
$this->expectedMetadata = $expectedMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSlug()
|
||||
{
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
@ -28,7 +38,7 @@ class TestPage
|
|||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
* @return string
|
||||
*/
|
||||
public function getSourceHTML()
|
||||
{
|
||||
|
@ -36,7 +46,7 @@ class TestPage
|
|||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
* @return string
|
||||
*/
|
||||
public function getExpectedHTML()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<section><p><strong>So finally you're <a href="http://fakehost/code/2013/testing-frontend-javascript-code-using-mocha-chai-and-sinon/">testing your frontend JavaScript code</a>? Great! The more you
|
||||
<section>
|
||||
<p><strong>So finally you're <a href="http://fakehost/code/2013/testing-frontend-javascript-code-using-mocha-chai-and-sinon/">testing your frontend JavaScript code</a>? Great! The more you
|
||||
write tests, the more confident you are with your code… but how much precisely?
|
||||
That's where <a href="http://en.wikipedia.org/wiki/Code_coverage">code coverage</a> might
|
||||
help.</strong>
|
||||
|
@ -15,9 +16,9 @@ help.</strong>
|
|||
actually works…</p>
|
||||
<blockquote>
|
||||
<p>Drinking game for web devs:
|
||||
<br></br>(1) Think of a noun
|
||||
<br></br>(2) Google "<noun>.js"
|
||||
<br></br>(3) If a library with that name exists - drink</p>— Shay Friedman (@ironshay)
|
||||
<br>(1) Think of a noun
|
||||
<br>(2) Google "<noun>.js"
|
||||
<br>(3) If a library with that name exists - drink</p>— Shay Friedman (@ironshay)
|
||||
<a href="https://twitter.com/ironshay/statuses/370525864523743232">August 22, 2013</a>
|
||||
</blockquote>
|
||||
<p><strong><a href="http://blanketjs.org/">Blanket.js</a></strong> is an <em>easy to install, easy to configure,
|
||||
|
@ -105,13 +106,16 @@ describe("Cow", function() {
|
|||
</code></pre>
|
||||
|
||||
<p><strong>Notes</strong>:</p>
|
||||
<ul><li>Notice the <code>data-cover</code> attribute we added to the script tag
|
||||
<ul>
|
||||
<li>Notice the <code>data-cover</code> attribute we added to the script tag
|
||||
loading the source of our library;</li>
|
||||
<li>The HTML test file <em>must</em> be served over HTTP for the adapter to
|
||||
be loaded.</li>
|
||||
</ul><p>Running the tests now gives us something like this:</p>
|
||||
</ul>
|
||||
<p>Running the tests now gives us something like this:</p>
|
||||
<p>
|
||||
<img alt="screenshot" src="http://fakehost/static/code/2013/blanket-coverage.png"></img></p>
|
||||
<img alt="screenshot" src="http://fakehost/static/code/2013/blanket-coverage.png">
|
||||
</p>
|
||||
<p>As you can see, the report at the bottom highlights that we haven't actually
|
||||
tested the case where an error is raised in case a target name is missing.
|
||||
We've been informed of that, nothing more, nothing less. We simply know
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<div id="content-main"><article role="article"><p>For more than a decade the Web has used XMLHttpRequest (XHR) to achieve
|
||||
<div id="content-main">
|
||||
<article role="article">
|
||||
<p>For more than a decade the Web has used XMLHttpRequest (XHR) to achieve
|
||||
asynchronous requests in JavaScript. While very useful, XHR is not a very
|
||||
nice API. It suffers from lack of separation of concerns. The input, output
|
||||
and state are all managed by interacting with one object, and state is
|
||||
|
@ -13,10 +15,12 @@
|
|||
<p>The <a href="https://fetch.spec.whatwg.org">Fetch specification</a>, which
|
||||
defines the API, nails down the semantics of a user agent fetching a resource.
|
||||
This, combined with ServiceWorkers, is an attempt to:</p>
|
||||
<ol><li>Improve the offline experience.</li>
|
||||
<ol>
|
||||
<li>Improve the offline experience.</li>
|
||||
<li>Expose the building blocks of the Web to the platform as part of the
|
||||
<a href="https://extensiblewebmanifesto.org/">extensible web movement</a>.</li>
|
||||
</ol><p>As of this writing, the Fetch API is available in Firefox 39 (currently
|
||||
</ol>
|
||||
<p>As of this writing, the Fetch API is available in Firefox 39 (currently
|
||||
Nightly) and Chrome 42 (currently dev). Github has a <a href="https://github.com/github/fetch">Fetch polyfill</a>.</p>
|
||||
|
||||
<h2>Feature detection</h2>
|
||||
|
@ -29,7 +33,6 @@
|
|||
<p>The most useful, high-level part of the Fetch API is the <code>fetch()</code> function.
|
||||
In its simplest form it takes a URL and returns a promise that resolves
|
||||
to the response. The response is captured as a <code>Response</code> object.</p>
|
||||
<div>
|
||||
<div><pre>fetch<span>(</span><span>"/data.json"</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span> <span>{</span>
|
||||
<span>// res instanceof Response == true.</span>
|
||||
<span>if</span> <span>(</span>res.<span>ok</span><span>)</span> <span>{</span>
|
||||
|
@ -42,9 +45,8 @@
|
|||
<span>}</span><span>,</span> <span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Fetch failed!"</span><span>,</span> e<span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>Submitting some parameters, it would look like this:</p>
|
||||
<div>
|
||||
<div><pre>fetch<span>(</span><span>"http://www.example.org/submit.php"</span><span>,</span> <span>{</span>
|
||||
method<span>:</span> <span>"POST"</span><span>,</span>
|
||||
headers<span>:</span> <span>{</span>
|
||||
|
@ -60,84 +62,84 @@
|
|||
<span>}</span><span>,</span> <span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
alert<span>(</span><span>"Error submitting form!"</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>The <code>fetch()</code> function’s arguments are the same as those passed
|
||||
to the
|
||||
<br></br><code>Request()</code> constructor, so you may directly pass arbitrarily
|
||||
<br>
|
||||
<code>Request()</code> constructor, so you may directly pass arbitrarily
|
||||
complex requests to <code>fetch()</code> as discussed below.</p>
|
||||
|
||||
<h2>Headers</h2>
|
||||
|
||||
<p>Fetch introduces 3 interfaces. These are <code>Headers</code>, <code>Request</code> and
|
||||
<br></br><code>Response</code>. They map directly to the underlying HTTP concepts,
|
||||
<br>
|
||||
<code>Response</code>. They map directly to the underlying HTTP concepts,
|
||||
but have
|
||||
<br></br>certain visibility filters in place for privacy and security reasons,
|
||||
<br>certain visibility filters in place for privacy and security reasons,
|
||||
such as
|
||||
<br></br>supporting CORS rules and ensuring cookies aren’t readable by third parties.</p>
|
||||
<br>supporting CORS rules and ensuring cookies aren’t readable by third parties.</p>
|
||||
<p>The <a href="https://fetch.spec.whatwg.org/#headers-class">Headers interface</a> is
|
||||
a simple multi-map of names to values:</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> content <span>=</span> <span>"Hello World"</span><span>;</span>
|
||||
<span>var</span> reqHeaders <span>=</span> <span>new</span> Headers<span>(</span><span>)</span><span>;</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"Content-Type"</span><span>,</span> <span>"text/plain"</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"Content-Length"</span><span>,</span> content.<span>length</span>.<span>toString</span><span>(</span><span>)</span><span>)</span><span>;</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"X-Custom-Header"</span><span>,</span> <span>"ProcessThisImmediately"</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>The same can be achieved by passing an array of arrays or a JS object
|
||||
literal
|
||||
<br></br>to the constructor:</p>
|
||||
<div>
|
||||
<br>to the constructor:</p>
|
||||
<div><pre>reqHeaders <span>=</span> <span>new</span> Headers<span>(</span><span>{</span>
|
||||
<span>"Content-Type"</span><span>:</span> <span>"text/plain"</span><span>,</span>
|
||||
<span>"Content-Length"</span><span>:</span> content.<span>length</span>.<span>toString</span><span>(</span><span>)</span><span>,</span>
|
||||
<span>"X-Custom-Header"</span><span>:</span> <span>"ProcessThisImmediately"</span><span>,</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>The contents can be queried and retrieved:</p>
|
||||
<div>
|
||||
<div><pre>console.<span>log</span><span>(</span>reqHeaders.<span>has</span><span>(</span><span>"Content-Type"</span><span>)</span><span>)</span><span>;</span> <span>// true</span>
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>has</span><span>(</span><span>"Set-Cookie"</span><span>)</span><span>)</span><span>;</span> <span>// false</span>
|
||||
reqHeaders.<span>set</span><span>(</span><span>"Content-Type"</span><span>,</span> <span>"text/html"</span><span>)</span><span>;</span>
|
||||
reqHeaders.<span>append</span><span>(</span><span>"X-Custom-Header"</span><span>,</span> <span>"AnotherValue"</span><span>)</span><span>;</span>
|
||||
|
||||
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>get</span><span>(</span><span>"Content-Length"</span><span>)</span><span>)</span><span>;</span> <span>// 11</span>
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>)</span><span>;</span> <span>// ["ProcessThisImmediately", "AnotherValue"]</span>
|
||||
|
||||
|
||||
reqHeaders.<span>delete</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</span><span>"X-Custom-Header"</span><span>)</span><span>)</span><span>;</span> <span>// []</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>Some of these operations are only useful in ServiceWorkers, but they provide
|
||||
<br></br>a much nicer API to Headers.</p>
|
||||
<br>a much nicer API to Headers.</p>
|
||||
<p>Since Headers can be sent in requests, or received in responses, and have
|
||||
various limitations about what information can and should be mutable, <code>Headers</code> objects
|
||||
have a <strong>guard</strong> property. This is not exposed to the Web, but
|
||||
it affects which mutation operations are allowed on the Headers object.
|
||||
<br></br>Possible values are:</p>
|
||||
<ul><li>“none”: default.</li>
|
||||
<br>Possible values are:</p>
|
||||
<ul>
|
||||
<li>“none”: default.</li>
|
||||
<li>“request”: guard for a Headers object obtained from a Request (<code>Request.headers</code>).</li>
|
||||
<li>“request-no-cors”: guard for a Headers object obtained from a Request
|
||||
created
|
||||
<br></br>with mode “no-cors”.</li>
|
||||
<br>with mode “no-cors”.</li>
|
||||
<li>“response”: naturally, for Headers obtained from Response (<code>Response.headers</code>).</li>
|
||||
<li>“immutable”: Mostly used for ServiceWorkers, renders a Headers object
|
||||
<br></br>read-only.</li>
|
||||
</ul><p>The details of how each guard affects the behaviors of the Headers object
|
||||
<br>read-only.</li>
|
||||
</ul>
|
||||
<p>The details of how each guard affects the behaviors of the Headers object
|
||||
are
|
||||
<br></br>in the <a href="https://fetch.spec.whatwg.org">specification</a>. For example,
|
||||
<br>in the <a href="https://fetch.spec.whatwg.org">specification</a>. For example,
|
||||
you may not append or set a “request” guarded Headers’ “Content-Length”
|
||||
header. Similarly, inserting “Set-Cookie” into a Response header is not
|
||||
allowed so that ServiceWorkers may not set cookies via synthesized Responses.</p>
|
||||
<p>All of the Headers methods throw TypeError if <code>name</code> is not a
|
||||
<a href="https://fetch.spec.whatwg.org/#concept-header-name">valid HTTP Header name</a>. The mutation operations will throw TypeError
|
||||
if there is an immutable guard. Otherwise they fail silently. For example:</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> res <span>=</span> Response.<span>error</span><span>(</span><span>)</span><span>;</span>
|
||||
<span>try</span> <span>{</span>
|
||||
res.<span>headers</span>.<span>set</span><span>(</span><span>"Origin"</span><span>,</span> <span>"http://mybank.com"</span><span>)</span><span>;</span>
|
||||
<span>}</span> <span>catch</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Cannot pretend to be a bank!"</span><span>)</span><span>;</span>
|
||||
<span>}</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<h2>Request</h2>
|
||||
|
||||
|
@ -146,26 +148,23 @@ console.<span>log</span><span>(</span>reqHeaders.<span>getAll</span><span>(</spa
|
|||
a body, a request mode, credentials and cache hints.</p>
|
||||
<p>The simplest Request is of course, just a URL, as you may do to GET a
|
||||
resource.</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> req <span>=</span> <span>new</span> Request<span>(</span><span>"/index.html"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>req.<span>method</span><span>)</span><span>;</span> <span>// "GET"</span>
|
||||
console.<span>log</span><span>(</span>req.<span>url</span><span>)</span><span>;</span> <span>// "http://example.com/index.html"</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>You may also pass a Request to the <code>Request()</code> constructor to
|
||||
create a copy.
|
||||
<br></br>(This is not the same as calling the <code>clone()</code> method, which
|
||||
<br>(This is not the same as calling the <code>clone()</code> method, which
|
||||
is covered in
|
||||
<br></br>the “Reading bodies” section.).</p>
|
||||
<div>
|
||||
<br>the “Reading bodies” section.).</p>
|
||||
<div><pre><span>var</span> copy <span>=</span> <span>new</span> Request<span>(</span>req<span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>copy.<span>method</span><span>)</span><span>;</span> <span>// "GET"</span>
|
||||
console.<span>log</span><span>(</span>copy.<span>url</span><span>)</span><span>;</span> <span>// "http://example.com/index.html"</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>Again, this form is probably only useful in ServiceWorkers.</p>
|
||||
<p>The non-URL attributes of the <code>Request</code> can only be set by passing
|
||||
initial
|
||||
<br></br>values as a second argument to the constructor. This argument is a dictionary.</p>
|
||||
<div>
|
||||
<br>values as a second argument to the constructor. This argument is a dictionary.</p>
|
||||
<div><pre><span>var</span> uploadReq <span>=</span> <span>new</span> Request<span>(</span><span>"/uploadImage"</span><span>,</span> <span>{</span>
|
||||
method<span>:</span> <span>"POST"</span><span>,</span>
|
||||
headers<span>:</span> <span>{</span>
|
||||
|
@ -173,7 +172,7 @@ console.<span>log</span><span>(</span>copy.<span>url</span><span>)</span><span>;
|
|||
<span>}</span><span>,</span>
|
||||
body<span>:</span> <span>"image data"</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>The Request’s mode is used to determine if cross-origin requests lead
|
||||
to valid responses, and which properties on the response are readable.
|
||||
Legal mode values are <code>"same-origin"</code>, <code>"no-cors"</code> (default)
|
||||
|
@ -181,15 +180,14 @@ console.<span>log</span><span>(</span>copy.<span>url</span><span>)</span><span>;
|
|||
<p>The <code>"same-origin"</code> mode is simple, if a request is made to another
|
||||
origin with this mode set, the result is simply an error. You could use
|
||||
this to ensure that
|
||||
<br></br>a request is always being made to your origin.</p>
|
||||
<div>
|
||||
<br>a request is always being made to your origin.</p>
|
||||
<div><pre><span>var</span> arbitraryUrl <span>=</span> document.<span>getElementById</span><span>(</span><span>"url-input"</span><span>)</span>.<span>value</span><span>;</span>
|
||||
fetch<span>(</span>arbitraryUrl<span>,</span> <span>{</span> mode<span>:</span> <span>"same-origin"</span> <span>}</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>res<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Response succeeded?"</span><span>,</span> res.<span>ok</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>,</span> <span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Please enter a same-origin URL!"</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>The <code>"no-cors"</code> mode captures what the web platform does by default
|
||||
for scripts you import from CDNs, images hosted on other domains, and so
|
||||
on. First, it prevents the method from being anything other than “HEAD”,
|
||||
|
@ -202,20 +200,19 @@ fetch<span>(</span>arbitraryUrl<span>,</span> <span>{</span> mode<span>:</span>
|
|||
<p><code>"cors"</code> mode is what you’ll usually use to make known cross-origin
|
||||
requests to access various APIs offered by other vendors. These are expected
|
||||
to adhere to
|
||||
<br></br>the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">CORS protocol</a>.
|
||||
<br>the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">CORS protocol</a>.
|
||||
Only a <a href="https://fetch.spec.whatwg.org/#concept-filtered-response-cors">limited set</a> of
|
||||
headers is exposed in the Response, but the body is readable. For example,
|
||||
you could get a list of Flickr’s <a href="https://www.flickr.com/services/api/flickr.interestingness.getList.html">most interesting</a> photos
|
||||
today like this:</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> u <span>=</span> <span>new</span> URLSearchParams<span>(</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'method'</span><span>,</span> <span>'flickr.interestingness.getList'</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'api_key'</span><span>,</span> <span>'<insert api key here>'</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'format'</span><span>,</span> <span>'json'</span><span>)</span><span>;</span>
|
||||
u.<span>append</span><span>(</span><span>'nojsoncallback'</span><span>,</span> <span>'1'</span><span>)</span><span>;</span>
|
||||
|
||||
|
||||
<span>var</span> apiCall <span>=</span> fetch<span>(</span><span>'https://api.flickr.com/services/rest?'</span> <span>+</span> u<span>)</span><span>;</span>
|
||||
|
||||
|
||||
apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>response<span>)</span> <span>{</span>
|
||||
<span>return</span> response.<span>json</span><span>(</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>json<span>)</span> <span>{</span>
|
||||
<span>// photo is a list of photos.</span>
|
||||
|
@ -226,25 +223,26 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
console.<span>log</span><span>(</span>photo.<span>title</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>You may not read out the “Date” header since Flickr does not allow it
|
||||
via
|
||||
<br></br><code>Access-Control-Expose-Headers</code>.</p>
|
||||
<div>
|
||||
<br>
|
||||
<code>Access-Control-Expose-Headers</code>.</p>
|
||||
<div><pre>response.<span>headers</span>.<span>get</span><span>(</span><span>"Date"</span><span>)</span><span>;</span> <span>// null</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>The <code>credentials</code> enumeration determines if cookies for the other
|
||||
domain are
|
||||
<br></br>sent to cross-origin requests. This is similar to XHR’s <code>withCredentials</code>
|
||||
<br></br>flag, but tri-valued as <code>"omit"</code> (default), <code>"same-origin"</code> and <code>"include"</code>.</p>
|
||||
<br>sent to cross-origin requests. This is similar to XHR’s <code>withCredentials</code>
|
||||
<br>flag, but tri-valued as <code>"omit"</code> (default), <code>"same-origin"</code> and <code>"include"</code>.</p>
|
||||
<p>The Request object will also give the ability to offer caching hints to
|
||||
the user-agent. This is currently undergoing some <a href="https://github.com/slightlyoff/ServiceWorker/issues/585">security review</a>.
|
||||
Firefox exposes the attribute, but it has no effect.</p>
|
||||
<p>Requests have two read-only attributes that are relevant to ServiceWorkers
|
||||
<br></br>intercepting them. There is the string <code>referrer</code>, which is
|
||||
<br>intercepting them. There is the string <code>referrer</code>, which is
|
||||
set by the UA to be
|
||||
<br></br>the referrer of the Request. This may be an empty string. The other is
|
||||
<br></br><code>context</code> which is a rather <a href="https://fetch.spec.whatwg.org/#requestcredentials">large enumeration</a> defining
|
||||
<br>the referrer of the Request. This may be an empty string. The other is
|
||||
<br>
|
||||
<code>context</code> which is a rather <a href="https://fetch.spec.whatwg.org/#requestcredentials">large enumeration</a> defining
|
||||
what sort of resource is being fetched. This could be “image” if the request
|
||||
is from an
|
||||
<img>tag in the controlled document, “worker” if it is an attempt to load a
|
||||
|
@ -265,39 +263,40 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
The <code>url</code> attribute reflects the URL of the corresponding request.</p>
|
||||
<p>Response also has a <code>type</code>, which is “basic”, “cors”, “default”,
|
||||
“error” or
|
||||
<br></br>“opaque”.</p>
|
||||
<ul><li><code>"basic"</code>: normal, same origin response, with all headers exposed
|
||||
<br>“opaque”.</p>
|
||||
<ul>
|
||||
<li><code>"basic"</code>: normal, same origin response, with all headers exposed
|
||||
except
|
||||
<br></br>“Set-Cookie” and “Set-Cookie2″.</li>
|
||||
<br>“Set-Cookie” and “Set-Cookie2″.</li>
|
||||
<li><code>"cors"</code>: response was received from a valid cross-origin request.
|
||||
<a href="https://fetch.spec.whatwg.org/#concept-filtered-response-cors">Certain headers and the body</a>may be accessed.</li>
|
||||
<li><code>"error"</code>: network error. No useful information describing
|
||||
the error is available. The Response’s status is 0, headers are empty and
|
||||
immutable. This is the type for a Response obtained from <code>Response.error()</code>.</li>
|
||||
<li><code>"opaque"</code>: response for “no-cors” request to cross-origin
|
||||
resource. <a href="https://fetch.spec.whatwg.org/#concept-filtered-response-opaque">Severely<br></br>
|
||||
resource. <a href="https://fetch.spec.whatwg.org/#concept-filtered-response-opaque">Severely<br>
|
||||
restricted</a>
|
||||
</li>
|
||||
</ul><p>The “error” type results in the <code>fetch()</code> Promise rejecting with
|
||||
</ul>
|
||||
<p>The “error” type results in the <code>fetch()</code> Promise rejecting with
|
||||
TypeError.</p>
|
||||
<p>There are certain attributes that are useful only in a ServiceWorker scope.
|
||||
The
|
||||
<br></br>idiomatic way to return a Response to an intercepted request in ServiceWorkers
|
||||
<br>idiomatic way to return a Response to an intercepted request in ServiceWorkers
|
||||
is:</p>
|
||||
<div>
|
||||
<div><pre>addEventListener<span>(</span><span>'fetch'</span><span>,</span> <span>function</span><span>(</span>event<span>)</span> <span>{</span>
|
||||
event.<span>respondWith</span><span>(</span><span>new</span> Response<span>(</span><span>"Response body"</span><span>,</span> <span>{</span>
|
||||
headers<span>:</span> <span>{</span> <span>"Content-Type"</span> <span>:</span> <span>"text/plain"</span> <span>}</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>As you can see, Response has a two argument constructor, where both arguments
|
||||
are optional. The first argument is a body initializer, and the second
|
||||
is a dictionary to set the <code>status</code>, <code>statusText</code> and <code>headers</code>.</p>
|
||||
<p>The static method <code>Response.error()</code> simply returns an error
|
||||
response. Similarly, <code>Response.redirect(url, status)</code> returns
|
||||
a Response resulting in
|
||||
<br></br>a redirect to <code>url</code>.</p>
|
||||
<br>a redirect to <code>url</code>.</p>
|
||||
|
||||
<h2>Dealing with bodies</h2>
|
||||
|
||||
|
@ -305,7 +304,8 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
over it because of the various data types body may contain, but we will
|
||||
cover it in detail now.</p>
|
||||
<p>A body is an instance of any of the following types.</p>
|
||||
<ul><li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a>
|
||||
<ul>
|
||||
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a>
|
||||
</li>
|
||||
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView">ArrayBufferView</a> (Uint8Array
|
||||
and friends)</li>
|
||||
|
@ -318,10 +318,12 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData">FormData</a> –
|
||||
currently not supported by either Gecko or Blink. Firefox expects to ship
|
||||
this in version 39 along with the rest of Fetch.</li>
|
||||
</ul><p>In addition, Request and Response both offer the following methods to
|
||||
</ul>
|
||||
<p>In addition, Request and Response both offer the following methods to
|
||||
extract their body. These all return a Promise that is eventually resolved
|
||||
with the actual content.</p>
|
||||
<ul><li><code>arrayBuffer()</code>
|
||||
<ul>
|
||||
<li><code>arrayBuffer()</code>
|
||||
</li>
|
||||
<li><code>blob()</code>
|
||||
</li>
|
||||
|
@ -331,21 +333,20 @@ apiCall.<span>then</span><span>(</span><span>function</span><span>(</span>respon
|
|||
</li>
|
||||
<li><code>formData()</code>
|
||||
</li>
|
||||
</ul><p>This is a significant improvement over XHR in terms of ease of use of
|
||||
</ul>
|
||||
<p>This is a significant improvement over XHR in terms of ease of use of
|
||||
non-text data!</p>
|
||||
<p>Request bodies can be set by passing <code>body</code> parameters:</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> form <span>=</span> <span>new</span> FormData<span>(</span>document.<span>getElementById</span><span>(</span><span>'login-form'</span><span>)</span><span>)</span><span>;</span>
|
||||
fetch<span>(</span><span>"/login"</span><span>,</span> <span>{</span>
|
||||
method<span>:</span> <span>"POST"</span><span>,</span>
|
||||
body<span>:</span> form
|
||||
<span>}</span><span>)</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>Responses take the first argument as the body.</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> res <span>=</span> <span>new</span> Response<span>(</span><span>new</span> File<span>(</span><span>[</span><span>"chunk"</span><span>,</span> <span>"chunk"</span><span>]</span><span>,</span> <span>"archive.zip"</span><span>,</span>
|
||||
<span>{</span> type<span>:</span> <span>"application/zip"</span> <span>}</span><span>)</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>Both Request and Response (and by extension the <code>fetch()</code> function),
|
||||
will try to intelligently <a href="https://fetch.spec.whatwg.org/#concept-bodyinit-extract">determine the content type</a>.
|
||||
Request will also automatically set a “Content-Type” header if none is
|
||||
|
@ -356,18 +357,17 @@ fetch<span>(</span><span>"/login"</span><span>,</span> <span>{</span>
|
|||
<p>It is important to realise that Request and Response bodies can only be
|
||||
read once! Both interfaces have a boolean attribute <code>bodyUsed</code> to
|
||||
determine if it is safe to read or not.</p>
|
||||
<div>
|
||||
<div><pre><span>var</span> res <span>=</span> <span>new</span> Response<span>(</span><span>"one time use"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
res.<span>text</span><span>(</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>v<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span> <span>// true</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>res.<span>bodyUsed</span><span>)</span><span>;</span> <span>// true</span>
|
||||
|
||||
|
||||
res.<span>text</span><span>(</span><span>)</span>.<span>catch</span><span>(</span><span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
console.<span>log</span><span>(</span><span>"Tried to read already consumed Response"</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<p>This decision allows easing the transition to an eventual <a href="https://streams.spec.whatwg.org/">stream-based</a> Fetch
|
||||
API. The intention is to let applications consume data as it arrives, allowing
|
||||
for JavaScript to deal with larger files like videos, and perform things
|
||||
|
@ -381,22 +381,21 @@ res.<span>text</span><span>(</span><span>)</span>.<span>catch</span><span>(</spa
|
|||
will return a clone of the object, with a ‘new’ body. <code>clone()</code> MUST
|
||||
be called before the body of the corresponding object has been used. That
|
||||
is, <code>clone()</code> first, read later.</p>
|
||||
<div>
|
||||
<div><pre>addEventListener<span>(</span><span>'fetch'</span><span>,</span> <span>function</span><span>(</span>evt<span>)</span> <span>{</span>
|
||||
<span>var</span> sheep <span>=</span> <span>new</span> Response<span>(</span><span>"Dolly"</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>sheep.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
<span>var</span> clone <span>=</span> sheep.<span>clone</span><span>(</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>clone.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
|
||||
|
||||
clone.<span>text</span><span>(</span><span>)</span><span>;</span>
|
||||
console.<span>log</span><span>(</span>sheep.<span>bodyUsed</span><span>)</span><span>;</span> <span>// false</span>
|
||||
console.<span>log</span><span>(</span>clone.<span>bodyUsed</span><span>)</span><span>;</span> <span>// true</span>
|
||||
|
||||
|
||||
evt.<span>respondWith</span><span>(</span>cache.<span>add</span><span>(</span>sheep.<span>clone</span><span>(</span><span>)</span><span>)</span>.<span>then</span><span>(</span><span>function</span><span>(</span>e<span>)</span> <span>{</span>
|
||||
<span>return</span> sheep<span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span>
|
||||
<span>}</span><span>)</span><span>;</span></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<h2>Future improvements</h2>
|
||||
|
||||
|
@ -409,7 +408,11 @@ res.<span>text</span><span>(</span><span>)</span>.<span>catch</span><span>(</spa
|
|||
in the issues in the <a href="https://www.w3.org/Bugs/Public/buglist.cgi?product=WHATWG&component=Fetch&resolution=---">Fetch</a> and
|
||||
<a href="https://github.com/slightlyoff/ServiceWorker/issues">ServiceWorker</a>specifications.</p>
|
||||
<p>For a better web!</p>
|
||||
<p><em>The author would like to thank Andrea Marchesini, Anne van Kesteren and Ben<br></br>
|
||||
<p><em>The author would like to thank Andrea Marchesini, Anne van Kesteren and Ben<br>
|
||||
Kelly for helping with the specification and implementation.</em>
|
||||
</p>
|
||||
</article></div>
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
</div>
|
|
@ -1,4 +1,5 @@
|
|||
<article>
|
||||
<h2>Test document title</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<article>
|
||||
<h2>Test document title</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"Author": "By Daniel Kahn Gillmor, Senior Staff Technologist, ACLU Speech, Privacy, and Technology Project",
|
||||
"Direction": "ltr",
|
||||
"Excerpt": "I don't use Facebook. I'm not technophobic — I'm a geek. I've been using email since the early 1990s, I have accounts on hundreds of services around the net, and I do software development and internet protocol design both for work and for fun. I believe that a globe-spanning communications network like the internet can be a positive social force, and I publish much of my own work on the open web.",
|
||||
"Author": "Daniel Kahn Gillmor",
|
||||
"Direction": null,
|
||||
"Excerpt": "Facebook collects data about people who have never even opted in. But there are ways these non-users can protect themselves.",
|
||||
"Image": "https:\/\/www.aclu.org\/sites\/default\/files\/styles\/metatag_og_image_1200x630\/public\/field_share_image\/web18-facebook-socialshare-1200x628-v02.png?itok=p77cQjOm",
|
||||
"Title": "Facebook Is Tracking Me Even Though I’m Not on Facebook",
|
||||
"Title": "Facebook Is Tracking Me Even Though I\u2019m Not on Facebook",
|
||||
"SiteName": "American Civil Liberties Union"
|
||||
}
|
|
@ -107,7 +107,7 @@
|
|||
<strong>Opting out?</strong>
|
||||
</h3>
|
||||
<p>
|
||||
Some advertisers claim that you can "opt out" of their targeted advertising, and even offer <a href="http://optout.aboutads.info/">a centralized place meant to help you do so</a>. However, my experience with these tools isn't a positive one. They don't appear to work all of the time. (In a recent experiment I conducted, two advertisers’ opt-out mechanisms failed to take effect.) And while advertisers claim to allow the user to opt out of "interest-based ads," it's not clear that the opt-outs govern data collection itself, rather than just the use of the collected data for displaying ads. Moreover, opting out on their terms requires the use of third-party cookies, thereby enabling another mechanism that other advertisers can then exploit.
|
||||
Some advertisers claim that you can "opt out" of their targeted advertising, and even offer <a href="http://optout.aboutads.info/">a centralized place meant to help you do so</a>. However, my experience with these tools isn't a positive one. They don't appear to work all of the time. (In a recent experiment I conducted, two advertisers’ opt-out mechanisms failed to take effect.) And while advertisers claim to allow the user to opt out of "interest-based ads," it's not clear that the opt-outs govern data collection itself, rather than just the use of the collected data for displaying ads. Moreover, opting out on their terms requires the use of third-party cookies, thereby enabling another mechanism that other advertisers can then exploit.
|
||||
</p>
|
||||
<p>
|
||||
It's also not clear how they function over time: How frequently do I need to take these steps? Do they expire? How often should I check back to make sure I’m still opted out? I'd much prefer an approach requiring me to opt <em>in</em> to surveillance and targeting.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[
|
||||
"http:\/\/cdn.arstechnica.net\/wp-content\/uploads\/2015\/04\/server-crash-640x426.jpg"
|
||||
"https:\/\/cdn.arstechnica.net\/wp-content\/uploads\/2015\/04\/server-crash-640x215.jpg",
|
||||
"https:\/\/cdn.arstechnica.net\/wp-content\/uploads\/2015\/04\/server-crash-640x426.jpg"
|
||||
]
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"Author": "by Dan Goodin - Apr 16, 2015 8:02 pm UTC",
|
||||
"Author": "Dan Goodin - Apr 16, 2015 8:02 pm UTC",
|
||||
"Direction": null,
|
||||
"Excerpt": "Two-year-old bug exposes thousands of servers to crippling attack.",
|
||||
"Image": "http:\/\/cdn.arstechnica.net\/wp-content\/uploads\/2015\/04\/server-crash-640x426.jpg",
|
||||
"Image": "https:\/\/cdn.arstechnica.net\/wp-content\/uploads\/2015\/04\/server-crash-640x215.jpg",
|
||||
"Title": "Just-released Minecraft exploit makes it easy to crash game servers",
|
||||
"SiteName": "Ars Technica"
|
||||
}
|
|
@ -1,12 +1,40 @@
|
|||
<div>
|
||||
<header>
|
||||
<h4>
|
||||
Biz & IT —
|
||||
</h4>
|
||||
|
||||
<h2 itemprop="description">
|
||||
Two-year-old bug exposes thousands of servers to crippling attack.
|
||||
</h2>
|
||||
|
||||
</header>
|
||||
<div itemprop="articleBody">
|
||||
<figure><img height="331" src="http://cdn.arstechnica.net/wp-content/uploads/2015/04/server-crash-640x426.jpg" width="640"></img><figcaption>
|
||||
</figcaption></figure><p>A flaw in the wildly popular online game <em>Minecraft</em> makes it easy for just about anyone to crash the server hosting the game, according to a computer programmer who has released proof-of-concept code that exploits the vulnerability.</p>
|
||||
<p>"I thought a lot before writing this post," Pakistan-based developer Ammar Askar wrote in a <a href="http://blog.ammaraskar.com/minecraft-vulnerability-advisory">blog post published Thursday</a>, 21 months, he said, after privately reporting the bug to <em>Minecraft</em> developer Mojang. "On the one hand I don't want to expose thousands of servers to a major vulnerability, yet on the other hand Mojang has failed to act on it."</p>
|
||||
<p>The bug resides in the <a href="https://github.com/ammaraskar/pyCraft">networking internals of the <em>Minecraft </em>protocol</a>. It allows the contents of inventory slots to be exchanged, so that, among other things, items in players' hotbars are displayed automatically after logging in. <em>Minecraft</em> items can also store arbitrary metadata in a file format known as <a href="http://wiki.vg/NBT">Named Binary Tag (NBT)</a>, which allows complex data structures to be kept in hierarchical nests. Askar has released <a href="https://github.com/ammaraskar/pyCraft/tree/nbt_exploit">proof-of-concept attack code</a> he said exploits the vulnerability to crash any server hosting the game. Here's how it works.</p>
|
||||
<figure>
|
||||
<img src="https://cdn.arstechnica.net/wp-content/uploads/2015/04/server-crash-640x426.jpg" alt="Just-released Minecraft exploit makes it easy to crash game servers">
|
||||
<figcaption>
|
||||
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>
|
||||
A flaw in the wildly popular online game <em>Minecraft</em> makes it easy for just about anyone to crash the server hosting the game, according to a computer programmer who has released proof-of-concept code that exploits the vulnerability.
|
||||
</p>
|
||||
<p>
|
||||
"I thought a lot before writing this post," Pakistan-based developer Ammar Askar wrote in a <a href="http://blog.ammaraskar.com/minecraft-vulnerability-advisory">blog post published Thursday</a>, 21 months, he said, after privately reporting the bug to <em>Minecraft</em> developer Mojang. "On the one hand I don't want to expose thousands of servers to a major vulnerability, yet on the other hand Mojang has failed to act on it."
|
||||
</p>
|
||||
<p>
|
||||
The bug resides in the <a href="https://github.com/ammaraskar/pyCraft">networking internals of the <em>Minecraft</em> protocol</a>. It allows the contents of inventory slots to be exchanged, so that, among other things, items in players' hotbars are displayed automatically after logging in. <em>Minecraft</em> items can also store arbitrary metadata in a file format known as <a href="http://wiki.vg/NBT">Named Binary Tag (NBT)</a>, which allows complex data structures to be kept in hierarchical nests. Askar has released <a href="https://github.com/ammaraskar/pyCraft/tree/nbt_exploit">proof-of-concept attack code</a> he said exploits the vulnerability to crash any server hosting the game. Here's how it works.
|
||||
</p>
|
||||
<blockquote>
|
||||
<p>The vulnerability stems from the fact that the client is allowed to send the server information about certain slots. This, coupled with the NBT format’s nesting allows us to <em>craft</em> a packet that is incredibly complex for the server to deserialize but trivial for us to generate.</p>
|
||||
<p>In my case, I chose to create lists within lists, down to five levels. This is a json representation of what it looks like.</p>
|
||||
<div> <pre><code data-lang="javascript"><span>rekt</span><span>:</span> <span>{</span>
|
||||
<p>
|
||||
The vulnerability stems from the fact that the client is allowed to send the server information about certain slots. This, coupled with the NBT format’s nesting allows us to <em>craft</em> a packet that is incredibly complex for the server to deserialize but trivial for us to generate.
|
||||
</p>
|
||||
<p>
|
||||
In my case, I chose to create lists within lists, down to five levels. This is a json representation of what it looks like.
|
||||
</p>
|
||||
<div>
|
||||
<pre><code data-lang="javascript"><span>rekt</span><span>:</span> <span>{</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
<span>list</span><span>:</span> <span>[</span>
|
||||
|
@ -31,14 +59,33 @@
|
|||
<span>...</span>
|
||||
<span>]</span>
|
||||
<span>...</span>
|
||||
<span>}</span></code></pre> </div>
|
||||
<p>The root of the object, <code>rekt</code>, contains 300 lists. Each list has a list with 10 sublists, and each of those sublists has 10 of their own, up until 5 levels of recursion. That’s a total of <code>10^5 * 300 = 30,000,000</code> lists.</p>
|
||||
<p>And this isn’t even the theoretical maximum for this attack. Just the nbt data for this payload is 26.6 megabytes. But luckily Minecraft implements a way to compress large packets, lucky us! zlib shrinks down our evil data to a mere 39 kilobytes.</p>
|
||||
<p>Note: in previous versions of Minecraft, there was no protocol wide compression for big packets. Previously, NBT was sent compressed with gzip and prefixed with a signed short of its length, which reduced our maximum payload size to <code>2^15 - 1</code>. Now that the length is a varint capable of storing integers up to <code>2^28</code>, our potential for attack has increased significantly.</p>
|
||||
<p>When the server will decompress our data, it’ll have 27 megs in a buffer somewhere in memory, but that isn’t the bit that’ll kill it. When it attempts to parse it into NBT, it’ll create java representations of the objects meaning suddenly, the sever is having to create several million java objects including ArrayLists. This runs the server out of memory and causes tremendous CPU load.</p>
|
||||
<p>This vulnerability exists on almost all previous and current Minecraft versions as of 1.8.3, the packets used as attack vectors are the <a href="http://wiki.vg/Protocol#Player_Block_Placement">0x08: Block Placement Packet</a> and <a href="http://wiki.vg/Protocol#Creative_Inventory_Action">0x10: Creative Inventory Action</a>.</p>
|
||||
<p>The fix for this vulnerability isn’t exactly that hard, the client should never really send a data structure as complex as NBT of arbitrary size and if it must, some form of recursion and size limits should be implemented.</p>
|
||||
<p>These were the fixes that I recommended to Mojang 2 years ago.</p>
|
||||
</blockquote>
|
||||
<p>Ars is asking Mojang for comment and will update this post if company officials respond.</p>
|
||||
<span>}</span></code></pre>
|
||||
</div>
|
||||
<p>
|
||||
The root of the object, <code>rekt</code>, contains 300 lists. Each list has a list with 10 sublists, and each of those sublists has 10 of their own, up until 5 levels of recursion. That’s a total of <code>10^5 * 300 = 30,000,000</code> lists.
|
||||
</p>
|
||||
<p>
|
||||
And this isn’t even the theoretical maximum for this attack. Just the nbt data for this payload is 26.6 megabytes. But luckily Minecraft implements a way to compress large packets, lucky us! zlib shrinks down our evil data to a mere 39 kilobytes.
|
||||
</p>
|
||||
<p>
|
||||
Note: in previous versions of Minecraft, there was no protocol wide compression for big packets. Previously, NBT was sent compressed with gzip and prefixed with a signed short of its length, which reduced our maximum payload size to <code>2^15 - 1</code>. Now that the length is a varint capable of storing integers up to <code>2^28</code>, our potential for attack has increased significantly.
|
||||
</p>
|
||||
<p>
|
||||
When the server will decompress our data, it’ll have 27 megs in a buffer somewhere in memory, but that isn’t the bit that’ll kill it. When it attempts to parse it into NBT, it’ll create java representations of the objects meaning suddenly, the sever is having to create several million java objects including ArrayLists. This runs the server out of memory and causes tremendous CPU load.
|
||||
</p>
|
||||
<p>
|
||||
This vulnerability exists on almost all previous and current Minecraft versions as of 1.8.3, the packets used as attack vectors are the <a href="http://wiki.vg/Protocol#Player_Block_Placement">0x08: Block Placement Packet</a> and <a href="http://wiki.vg/Protocol#Creative_Inventory_Action">0x10: Creative Inventory Action</a>.
|
||||
</p>
|
||||
<p>
|
||||
The fix for this vulnerability isn’t exactly that hard, the client should never really send a data structure as complex as NBT of arbitrary size and if it must, some form of recursion and size limits should be implemented.
|
||||
</p>
|
||||
<p>
|
||||
These were the fixes that I recommended to Mojang 2 years ago.
|
||||
</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
Ars is asking Mojang for comment and will update this post if company officials respond.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"0": "http:\/\/fakehost\/test\/base\/foo\/bar\/baz.png",
|
||||
"2": "http:\/\/fakehost\/foo\/bar\/baz.png",
|
||||
"3": "http:\/\/test\/foo\/bar\/baz.png",
|
||||
"4": "https:\/\/test\/foo\/bar\/baz.png"
|
||||
}
|
||||
[
|
||||
"http:\/\/fakehost\/test\/base\/foo\/bar\/baz.png",
|
||||
"http:\/\/fakehost\/foo\/bar\/baz.png",
|
||||
"http:\/\/test\/foo\/bar\/baz.png",
|
||||
"https:\/\/test\/foo\/bar\/baz.png"
|
||||
]
|
|
@ -1,4 +1,5 @@
|
|||
<article>
|
||||
<h2>Lorem</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
@ -17,11 +18,11 @@
|
|||
<p><a href="http://test/foo/bar/baz.html">link</a></p>
|
||||
<p><a href="https://test/foo/bar/baz.html">link</a></p>
|
||||
<p>Images</p>
|
||||
<p><img src="http://fakehost/test/base/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/test/base/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="https://test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/test/base/foo/bar/baz.png"></p>
|
||||
<p><img src="http://fakehost/test/base/foo/bar/baz.png"></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></p>
|
||||
<p><img src="http://test/foo/bar/baz.png"></p>
|
||||
<p><img src="https://test/foo/bar/baz.png"></p>
|
||||
<h2>Foo</h2>
|
||||
<p>
|
||||
Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"0": "http:\/\/fakehost\/foo\/bar\/baz.png",
|
||||
"3": "http:\/\/test\/foo\/bar\/baz.png",
|
||||
"4": "https:\/\/test\/foo\/bar\/baz.png"
|
||||
}
|
||||
[
|
||||
"http:\/\/fakehost\/foo\/bar\/baz.png",
|
||||
"http:\/\/test\/foo\/bar\/baz.png",
|
||||
"https:\/\/test\/foo\/bar\/baz.png"
|
||||
]
|
|
@ -1,4 +1,5 @@
|
|||
<article>
|
||||
<h2>Lorem</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
@ -17,11 +18,11 @@
|
|||
<p><a href="http://test/foo/bar/baz.html">link</a></p>
|
||||
<p><a href="https://test/foo/bar/baz.html">link</a></p>
|
||||
<p>Images</p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="https://test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></p>
|
||||
<p><img src="http://test/foo/bar/baz.png"></p>
|
||||
<p><img src="https://test/foo/bar/baz.png"></p>
|
||||
<h2>Foo</h2>
|
||||
<p>
|
||||
Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"0": "http:\/\/fakehost\/test\/foo\/bar\/baz.png",
|
||||
"2": "http:\/\/fakehost\/foo\/bar\/baz.png",
|
||||
"3": "http:\/\/test\/foo\/bar\/baz.png",
|
||||
"4": "https:\/\/test\/foo\/bar\/baz.png"
|
||||
}
|
||||
[
|
||||
"http:\/\/fakehost\/test\/foo\/bar\/baz.png",
|
||||
"http:\/\/fakehost\/foo\/bar\/baz.png",
|
||||
"http:\/\/test\/foo\/bar\/baz.png",
|
||||
"https:\/\/test\/foo\/bar\/baz.png"
|
||||
]
|
|
@ -1,4 +1,5 @@
|
|||
<article>
|
||||
<h2>Lorem</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
@ -17,11 +18,11 @@
|
|||
<p><a href="http://test/foo/bar/baz.html">link</a></p>
|
||||
<p><a href="https://test/foo/bar/baz.html">link</a></p>
|
||||
<p>Images</p>
|
||||
<p><img src="http://fakehost/test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="https://test/foo/bar/baz.png"></img></p>
|
||||
<p><img src="http://fakehost/test/foo/bar/baz.png"></p>
|
||||
<p><img src="http://fakehost/test/foo/bar/baz.png"></p>
|
||||
<p><img src="http://fakehost/foo/bar/baz.png"></p>
|
||||
<p><img src="http://test/foo/bar/baz.png"></p>
|
||||
<p><img src="https://test/foo/bar/baz.png"></p>
|
||||
<h2>Foo</h2>
|
||||
<p>
|
||||
Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"0": "http:\/\/ichef.bbci.co.uk\/news\/1024\/cpsprodpb\/3D8B\/production\/_84455751_84455749.jpg",
|
||||
"1": "http:\/\/ichef.bbci.co.uk\/news\/555\/cpsprodpb\/462D\/production\/_84456971_gettyimages-167501087.jpg",
|
||||
"2": "http:\/\/ichef.bbci.co.uk\/news\/555\/media\/images\/76020000\/jpg\/_76020974_line976.jpg",
|
||||
"3": "http:\/\/ichef-1.bbci.co.uk\/news\/555\/cpsprodpb\/6D3D\/production\/_84456972_p072315al-0500.jpg",
|
||||
"5": "http:\/\/ichef-1.bbci.co.uk\/news\/555\/cpsprodpb\/142FD\/production\/_84458628_shirtreuters.jpg"
|
||||
}
|
||||
[
|
||||
"http:\/\/ichef.bbci.co.uk\/news\/1024\/cpsprodpb\/3D8B\/production\/_84455751_84455749.jpg",
|
||||
"http:\/\/ichef.bbci.co.uk\/news\/555\/cpsprodpb\/462D\/production\/_84456971_gettyimages-167501087.jpg",
|
||||
"http:\/\/ichef.bbci.co.uk\/news\/555\/media\/images\/76020000\/jpg\/_76020974_line976.jpg",
|
||||
"http:\/\/ichef-1.bbci.co.uk\/news\/555\/cpsprodpb\/6D3D\/production\/_84456972_p072315al-0500.jpg",
|
||||
"http:\/\/ichef-1.bbci.co.uk\/news\/555\/cpsprodpb\/142FD\/production\/_84458628_shirtreuters.jpg"
|
||||
]
|
|
@ -3,6 +3,6 @@
|
|||
"Direction": null,
|
||||
"Excerpt": "President Barack Obama tells the BBC his failure to pass \"common sense gun safety laws\" is the greatest frustration of his presidency.",
|
||||
"Image": "http:\/\/ichef.bbci.co.uk\/news\/1024\/cpsprodpb\/3D8B\/production\/_84455751_84455749.jpg",
|
||||
"Title": "Obama admits US gun laws are his 'biggest frustration' - BBC News",
|
||||
"Title": "Obama admits US gun laws are his 'biggest frustration'",
|
||||
"SiteName": "BBC News"
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<div property="articleBody">
|
||||
<p>President Barack Obama has admitted that his failure to pass "common sense gun safety laws" in the US is the greatest frustration of his presidency. </p><p>In an interview with the BBC, Mr Obama said it was "distressing" not to have made progress on the issue "even in the face of repeated mass killings".</p><p>He vowed to keep trying, but the BBC's North America editor Jon Sopel said the president did not sound very confident. </p><p>However, Mr Obama said race relations had improved during his presidency. </p><p>Hours after the interview, a gunman opened fire at a cinema in the US state of Louisiana, killing two people and injuring several others before shooting himself.</p><p>In a wide-ranging interview, President Obama also said:</p><ul><li>
|
||||
<p>President Barack Obama has admitted that his failure to pass "common sense gun safety laws" in the US is the greatest frustration of his presidency. </p><p>In an interview with the BBC, Mr Obama said it was "distressing" not to have made progress on the issue "even in the face of repeated mass killings".</p><p>He vowed to keep trying, but the BBC's North America editor Jon Sopel said the president did not sound very confident. </p><p>However, Mr Obama said race relations had improved during his presidency. </p><p>Hours after the interview, a gunman opened fire at a cinema in the US state of Louisiana, killing two people and injuring several others before shooting himself.</p><p>In a wide-ranging interview, President Obama also said:</p><ul>
|
||||
<li>
|
||||
<a href="http://www.bbc.co.uk/news/uk-politics-33647154">The UK must stay in the EU</a> to have influence on the world stage</li>
|
||||
<li>He is confident the Iran nuclear deal will be passed by Congress </li>
|
||||
<li>Syria needs a political solution in order to defeat the Islamic State group</li>
|
||||
|
@ -7,10 +8,14 @@
|
|||
</li>
|
||||
<li>He would defend his advocacy of gay rights following protests in Kenya</li>
|
||||
<li>Despite racial tensions, the US is becoming more diverse and more tolerant</li>
|
||||
</ul><p><a href="http://www.bbc.co.uk/news/world-us-canada-33646542">Read the full transcript of his interview</a></p><p>Mr Obama lands in Kenya later on Friday for his first visit since becoming president. </p><p>But with just 18 months left in power, he said gun control was the area where he has been "most frustrated and most stymied" since coming to power in 2009.</p><p>"If you look at the number of Americans killed since 9/11 by terrorism, it's less than 100. If you look at the number that have been killed by gun violence, it's in the tens of thousands," Mr Obama said. </p><figure><img alt="Gun control campaigners protest in McPhearson Square in Washington DC - 25 April 2013" datasrc="http://ichef.bbci.co.uk/news/976/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" height="549" src="http://ichef.bbci.co.uk/news/555/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" width="976"></img><figcaption><span>
|
||||
</ul><p><a href="http://www.bbc.co.uk/news/world-us-canada-33646542">Read the full transcript of his interview</a></p><p>Mr Obama lands in Kenya later on Friday for his first visit since becoming president. </p><p>But with just 18 months left in power, he said gun control was the area where he has been "most frustrated and most stymied" since coming to power in 2009.</p><p>"If you look at the number of Americans killed since 9/11 by terrorism, it's less than 100. If you look at the number that have been killed by gun violence, it's in the tens of thousands," Mr Obama said. </p><figure><img src="http://ichef.bbci.co.uk/news/555/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" datasrc="http://ichef.bbci.co.uk/news/976/cpsprodpb/462D/production/_84456971_gettyimages-167501087.jpg" alt="Gun control campaigners protest in McPhearson Square in Washington DC - 25 April 2013" height="549" width="976">
|
||||
<figcaption>
|
||||
<span>
|
||||
The president said he would continue fighting for greater gun control laws
|
||||
</span>
|
||||
</figcaption></figure><p>"For us not to be able to resolve that issue has been something that is distressing," he added. </p><p>Mr Obama has pushed for stricter gun control throughout his presidency but has been unable to secure any significant changes to the laws. </p><p>After nine African-American churchgoers were killed in South Carolina in June, he admitted "politics in this town" meant there were few options available.</p><figure><img alt="line" datasrc="http://ichef.bbci.co.uk/news/464/media/images/76020000/jpg/_76020974_line976.jpg" height="2" src="http://ichef.bbci.co.uk/news/555/media/images/76020000/jpg/_76020974_line976.jpg" width="464"></img></figure><h2>Analysis: Jon Sopel, BBC News, Washington</h2><figure><img alt="President Barack Obama participates in an interview with Jon Sopel of BBC in the Roosevelt Room of the White House - 23 July 2015" datasrc="http://ichef-1.bbci.co.uk/news/976/cpsprodpb/6D3D/production/_84456972_p072315al-0500.jpg" height="549" src="http://ichef-1.bbci.co.uk/news/555/cpsprodpb/6D3D/production/_84456972_p072315al-0500.jpg" width="976"></img></figure><p>Nine months ago, the president seemed like a spent force, after taking a beating in the midterm elections, during which members of his own party were reluctant to campaign on his record. </p><p>But the man sat before me today was relaxed and confident, buoyed by a string of "wins" on healthcare, Cuba and Iran, after bitter and ongoing battles with his many critics. </p><p>The only body swerve the president performed was when I asked him <a href="http://www.bbc.co.uk/news/world-us-canada-33643168"> how many minds he had changed on the Iran nuclear deal </a>after an intense sell aimed at Gulf allies and members of US Congress who remain implacably opposed. </p><p>There was a momentary flicker across the president's face as if to say "You think you got me?" before his smile returned and he proceeded to talk about how Congress would come round.</p><p>But notably, he did not give a direct answer to that question, which leaves me with the impression that he has persuaded precisely zero.</p><p><a href="http://www.bbc.co.uk/news/world-us-canada-33646875">Five things we learned from Obama interview</a></p><p><a href="http://www.bbc.co.uk/news/world-us-canada-33646545">The presidential body swerve</a></p><figure><img alt="line" datasrc="http://ichef.bbci.co.uk/news/464/media/images/76020000/jpg/_76020974_line976.jpg" height="2" src="http://ichef.bbci.co.uk/news/555/media/images/76020000/jpg/_76020974_line976.jpg" width="464"></img></figure><p>On race relations, Mr Obama said recent concerns around policing and mass incarcerations were "legitimate and deserve intense attention" but insisted progress had been made. </p><p>Children growing up during the eight years of his presidency "will have a different view of race relations in this country and what's possible," he said. </p><p>"There are going to be tensions that arise. But if you look at my daughters' generation, they have an attitude about race that's entirely different than even my generation."</p><p>Talking about how he was feeling after his recent successes, he said "every president, every leader has strengths and weaknesses". </p><p>"One of my strengths is I have a pretty even temperament. I don't get too high when it's high and I don't get too low when it's low," he said. </p><figure><img alt="Customer looks at Obama shirts at a stall in Nairobi's Kibera slums, 23 July 2015" datasrc="http://ichef-1.bbci.co.uk/news/976/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" height="549" src="http://ichef-1.bbci.co.uk/news/555/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" width="976"></img><figcaption><span>
|
||||
</figcaption></figure><p>"For us not to be able to resolve that issue has been something that is distressing," he added. </p><p>Mr Obama has pushed for stricter gun control throughout his presidency but has been unable to secure any significant changes to the laws. </p><p>After nine African-American churchgoers were killed in South Carolina in June, he admitted "politics in this town" meant there were few options available.</p><figure><img src="http://ichef.bbci.co.uk/news/555/media/images/76020000/jpg/_76020974_line976.jpg" datasrc="http://ichef.bbci.co.uk/news/464/media/images/76020000/jpg/_76020974_line976.jpg" alt="line" height="2" width="464"></figure><h2>Analysis: Jon Sopel, BBC News, Washington</h2><figure><img src="http://ichef-1.bbci.co.uk/news/555/cpsprodpb/6D3D/production/_84456972_p072315al-0500.jpg" datasrc="http://ichef-1.bbci.co.uk/news/976/cpsprodpb/6D3D/production/_84456972_p072315al-0500.jpg" alt="President Barack Obama participates in an interview with Jon Sopel of BBC in the Roosevelt Room of the White House - 23 July 2015" height="549" width="976"></figure><p>Nine months ago, the president seemed like a spent force, after taking a beating in the midterm elections, during which members of his own party were reluctant to campaign on his record. </p><p>But the man sat before me today was relaxed and confident, buoyed by a string of "wins" on healthcare, Cuba and Iran, after bitter and ongoing battles with his many critics. </p><p>The only body swerve the president performed was when I asked him <a href="http://www.bbc.co.uk/news/world-us-canada-33643168"> how many minds he had changed on the Iran nuclear deal </a>after an intense sell aimed at Gulf allies and members of US Congress who remain implacably opposed. </p><p>There was a momentary flicker across the president's face as if to say "You think you got me?" before his smile returned and he proceeded to talk about how Congress would come round.</p><p>But notably, he did not give a direct answer to that question, which leaves me with the impression that he has persuaded precisely zero.</p><p><a href="http://www.bbc.co.uk/news/world-us-canada-33646875">Five things we learned from Obama interview</a></p><p><a href="http://www.bbc.co.uk/news/world-us-canada-33646545">The presidential body swerve</a></p><figure><img src="http://ichef.bbci.co.uk/news/555/media/images/76020000/jpg/_76020974_line976.jpg" datasrc="http://ichef.bbci.co.uk/news/464/media/images/76020000/jpg/_76020974_line976.jpg" alt="line" height="2" width="464"></figure><p>On race relations, Mr Obama said recent concerns around policing and mass incarcerations were "legitimate and deserve intense attention" but insisted progress had been made. </p><p>Children growing up during the eight years of his presidency "will have a different view of race relations in this country and what's possible," he said. </p><p>"There are going to be tensions that arise. But if you look at my daughters' generation, they have an attitude about race that's entirely different than even my generation."</p><p>Talking about how he was feeling after his recent successes, he said "every president, every leader has strengths and weaknesses". </p><p>"One of my strengths is I have a pretty even temperament. I don't get too high when it's high and I don't get too low when it's low," he said. </p><figure><img src="http://ichef-1.bbci.co.uk/news/555/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" datasrc="http://ichef-1.bbci.co.uk/news/976/cpsprodpb/142FD/production/_84458628_shirtreuters.jpg" alt="Customer looks at Obama shirts at a stall in Nairobi's Kibera slums, 23 July 2015" height="549" width="976">
|
||||
<figcaption>
|
||||
<span>
|
||||
Kenya is getting ready to welcome the US president
|
||||
</span>
|
||||
</figcaption></figure><h2>Kenya trip</h2><p>Mr Obama was speaking to the BBC at the White House before departing for Kenya.</p><p>His father was Kenyan and the president is expected to meet relatives in Nairobi.</p><p>Mr Obama has faced criticism in the country after the US legalised gay marriage. However, in his interview, the president said he would not fall silent on the issue.</p><p>"I am not a fan of discrimination and bullying of anybody on the basis of race, on the basis of religion, on the basis of sexual orientation or gender," he said.</p><p>The president also admitted that some African governments, including Kenya's, needed to improve their records on human rights and democracy. However, he defended his decision to engage with and visit those governments. </p><p>"Well, they're not ideal institutions. But what we found is, is that when we combined blunt talk with engagement, that gives us the best opportunity to influence and open up space for civil society." </p><p>Mr Obama will become the first US president to address the African Union when he travels on to Ethiopia on Sunday.</p>
|
||||
|
|
|
@ -1,46 +1,73 @@
|
|||
<div id="post-body-932306423056216142" itemprop="description articleBody"><p>
|
||||
I've written a couple of posts in the past few months but they were all for <a href="http://blog.ioactive.com/search/label/Andrew%20Zonenberg">the blog at work</a> so I figured I'm long overdue for one on Silicon Exposed.</p><h2>
|
||||
So what's a GreenPak?</h2>
|
||||
<p> Silego Technology is a fabless semiconductor company located in the SF Bay area, which makes (among other things) a line of programmable logic devices known as GreenPak. Their <a href="http://www.silego.com/products/greenpak5.html">5th generation parts</a> were just announced, but I started this project before that happened so I'm still targeting the <a href="http://www.silego.com/products/greenpak4.html">4th generation</a>.</p><p> GreenPak devices are kind of like itty bitty <a href="http://www.cypress.com/products/32-bit-arm-cortex-m-psoc">PSoCs</a> - they have a mixed signal fabric with an ADC, DACs, comparators, voltage references, plus a digital LUT/FF fabric and some typical digital MCU peripherals like counters and oscillators (but no CPU).</p><p> It's actually an interesting architecture - FPGAs (including some devices marketed as CPLDs) are a 2D array of LUTs connected via wires to adjacent cells, and true (product term) CPLDs are a star topology of AND-OR arrays connected by a crossbar. GreenPak, on the other hand, is a star topology of LUTs, flipflops, and analog/digital hard IP connected to a crossbar.</p><p> Without further ado, here's a block diagram showing all the cool stuff you get in the SLG46620V:</p><table readabilityDataTable="0"><tbody><tr><td>
|
||||
<a href="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s1600/block-diagram.png" imageanchor="1"><img height="512" src="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s640/block-diagram.png" width="640"></img></a>
|
||||
<p> Silego Technology is a fabless semiconductor company located in the SF Bay area, which makes (among other things) a line of programmable logic devices known as GreenPak. Their <a href="http://www.silego.com/products/greenpak5.html">5th generation parts</a> were just announced, but I started this project before that happened so I'm still targeting the <a href="http://www.silego.com/products/greenpak4.html">4th generation</a>.</p><p> GreenPak devices are kind of like itty bitty <a href="http://www.cypress.com/products/32-bit-arm-cortex-m-psoc">PSoCs</a> - they have a mixed signal fabric with an ADC, DACs, comparators, voltage references, plus a digital LUT/FF fabric and some typical digital MCU peripherals like counters and oscillators (but no CPU).</p><p> It's actually an interesting architecture - FPGAs (including some devices marketed as CPLDs) are a 2D array of LUTs connected via wires to adjacent cells, and true (product term) CPLDs are a star topology of AND-OR arrays connected by a crossbar. GreenPak, on the other hand, is a star topology of LUTs, flipflops, and analog/digital hard IP connected to a crossbar.</p><p> Without further ado, here's a block diagram showing all the cool stuff you get in the SLG46620V:</p><table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s1600/block-diagram.png" imageanchor="1"><img height="512" src="https://1.bp.blogspot.com/-YIPC5jkXkDE/Vy7YPSqFKWI/AAAAAAAAAxI/a7D6Ji2GxoUvcrwUkI4RLZcr2LFQEJCTACLcB/s640/block-diagram.png" width="640"></a>
|
||||
</td>
|
||||
</tr><tr><td>SLG46620V block diagram (from device datasheet)</td>
|
||||
</tr></tbody></table><p>
|
||||
They're also tiny (the SLG46620V is a 20-pin 0.4mm pitch STQFN measuring 2x3 mm, and the lower gate count SLG46140V is a mere 1.6x2 mm) and probably the cheapest programmable logic device on the market - $0.50 in low volume and less than $0.40 in larger quantities.</p><p> The Vdd range of GreenPak4 is huge, more like what you'd expect from an MCU than an FPGA! It can run on anything from 1.8 to 5V, although performance is only specified at 1.8, 3.3, and 5V nominal voltages. There's also a dual-rail version that trades one of the GPIO pins for a second power supply pin, allowing you to interface to logic at two different voltage levels.</p><p> To support low-cost/space-constrained applications, they even have the configuration memory on die. It's one-time programmable and needs external Vpp to program (presumably Silego didn't want to waste die area on charge pumps that would only be used once) but has a SRAM programming mode for prototyping.</p><p> The best part is that the development software (GreenPak Designer) is free of charge and provided for all major operating systems including Linux! Unfortunately, the only supported design entry method is schematic entry and there's no way to write your design in a HDL.</p><p> While schematics may be fine for quick tinkering on really simple designs, they quickly get unwieldy. The nightmare of a circuit shown below is just a bunch of counters hooked up to LEDs that blink at various rates.</p><table readabilityDataTable="0"><tbody><tr><td>
|
||||
<a href="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s1600/schematic-from-hell.png" imageanchor="1"><img height="334" src="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s640/schematic-from-hell.png" width="640"></img></a>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SLG46620V block diagram (from device datasheet)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table><p>
|
||||
They're also tiny (the SLG46620V is a 20-pin 0.4mm pitch STQFN measuring 2x3 mm, and the lower gate count SLG46140V is a mere 1.6x2 mm) and probably the cheapest programmable logic device on the market - $0.50 in low volume and less than $0.40 in larger quantities.</p><p> The Vdd range of GreenPak4 is huge, more like what you'd expect from an MCU than an FPGA! It can run on anything from 1.8 to 5V, although performance is only specified at 1.8, 3.3, and 5V nominal voltages. There's also a dual-rail version that trades one of the GPIO pins for a second power supply pin, allowing you to interface to logic at two different voltage levels.</p><p> To support low-cost/space-constrained applications, they even have the configuration memory on die. It's one-time programmable and needs external Vpp to program (presumably Silego didn't want to waste die area on charge pumps that would only be used once) but has a SRAM programming mode for prototyping.</p><p> The best part is that the development software (GreenPak Designer) is free of charge and provided for all major operating systems including Linux! Unfortunately, the only supported design entry method is schematic entry and there's no way to write your design in a HDL.</p><p> While schematics may be fine for quick tinkering on really simple designs, they quickly get unwieldy. The nightmare of a circuit shown below is just a bunch of counters hooked up to LEDs that blink at various rates.</p><table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s1600/schematic-from-hell.png" imageanchor="1"><img height="334" src="https://1.bp.blogspot.com/-k3naUT3uXao/Vy7WFac246I/AAAAAAAAAw8/mePy_ostO8QJra5ZJrbP2WGhTlJ0B_r8gCLcB/s640/schematic-from-hell.png" width="640"></a>
|
||||
</td>
|
||||
</tr><tr><td>Schematic from hell!</td>
|
||||
</tr></tbody></table><p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Schematic from hell!</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table><p>
|
||||
As if this wasn't enough of a problem, the largest GreenPak4 device (the SLG46620V) is split into two halves with limited routing between them, and the GUI doesn't help the user manage this complexity at all - you have to draw your schematic in two halves and add "cross connections" between them.</p><p> The icing on the cake is that schematics are a pain to diff and collaborate on. Although GreenPak schematics are XML based, which is a touch better than binary, who wants to read a giant XML diff and try to figure out what's going on in the circuit?</p><p> This isn't going to be a post on the quirks of Silego's software, though - that would be boring. As it turns out, there's one more exciting feature of these chips that I didn't mention earlier: the configuration bitstream is 100% documented in the device datasheet! This is unheard of in the programmable logic world. As Nick of Arachnid Labs <a href="http://www.arachnidlabs.com/blog/2015/03/30/greenpak/">says</a>, the chip is "just dying for someone to write a VHDL or Verilog compiler for it". As you can probably guess by from the title of this post, I've been busy doing exactly that.</p><h2>
|
||||
Great! How does it work?</h2>
|
||||
<p> Rather than wasting time writing a synthesizer, I decided to write a GreenPak technology library for Clifford Wolf's excellent open source synthesis tool, <a href="http://www.clifford.at/yosys/">Yosys</a>, and then make a place-and-route tool to turn that into a final netlist. The post-PAR netlist can then be loaded into GreenPak Designer in order to program the device.</p><p> The first step of the process is to run the "synth_greenpak4" Yosys flow on the Verilog source. This runs a generic RTL synthesis pass, then some coarse-grained extraction passes to infer shift register and counter cells from behavioral logic, and finally maps the remaining logic to LUT/FF cells and outputs a JSON-formatted netlist.</p><p> Once the design has been synthesized, my tool (named, surprisingly, gp4par) is then launched on the netlist. It begins by parsing the JSON and constructing a directed graph of cell objects in memory. A second graph, containing all of the primitives in the device and the legal connections between them, is then created based on the device specified on the command line. (As of now only the SLG46620V is supported; the SLG46621V can be added fairly easily but the SLG46140V has a slightly different microarchitecture which will require a bit more work to support.)</p><p> After the graphs are generated, each node in the netlist graph is assigned a numeric label identifying the type of cell and each node in the device graph is assigned a list of legal labels: for example, an I/O buffer site is legal for an input buffer, output buffer, or bidirectional buffer.</p><table readabilityDataTable="0"><tbody><tr><td>
|
||||
<a href="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s1600/graph-labels.png" imageanchor="1"><img height="141" src="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s400/graph-labels.png" width="400"></img></a>
|
||||
<p> Rather than wasting time writing a synthesizer, I decided to write a GreenPak technology library for Clifford Wolf's excellent open source synthesis tool, <a href="http://www.clifford.at/yosys/">Yosys</a>, and then make a place-and-route tool to turn that into a final netlist. The post-PAR netlist can then be loaded into GreenPak Designer in order to program the device.</p><p> The first step of the process is to run the "synth_greenpak4" Yosys flow on the Verilog source. This runs a generic RTL synthesis pass, then some coarse-grained extraction passes to infer shift register and counter cells from behavioral logic, and finally maps the remaining logic to LUT/FF cells and outputs a JSON-formatted netlist.</p><p> Once the design has been synthesized, my tool (named, surprisingly, gp4par) is then launched on the netlist. It begins by parsing the JSON and constructing a directed graph of cell objects in memory. A second graph, containing all of the primitives in the device and the legal connections between them, is then created based on the device specified on the command line. (As of now only the SLG46620V is supported; the SLG46621V can be added fairly easily but the SLG46140V has a slightly different microarchitecture which will require a bit more work to support.)</p><p> After the graphs are generated, each node in the netlist graph is assigned a numeric label identifying the type of cell and each node in the device graph is assigned a list of legal labels: for example, an I/O buffer site is legal for an input buffer, output buffer, or bidirectional buffer.</p><table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s1600/graph-labels.png" imageanchor="1"><img height="141" src="https://2.bp.blogspot.com/-kIekczO693g/Vy7dBqYifXI/AAAAAAAAAxc/hMNJBs5bedIQOrBzzkhq4gbmhR-n58EQwCLcB/s400/graph-labels.png" width="400"></a>
|
||||
</td>
|
||||
</tr><tr><td>Example labeling for a subset of the netlist and device graphs</td>
|
||||
</tr></tbody></table><p>
|
||||
The labeled nodes now need to be placed. The initial placement uses a simple greedy algorithm to create a valid (although not necessarily optimal or even routable) placement:</p><ol><li>Loop over the cells in the netlist. If any cell has a LOC constraint, which locks the cell to a specific physical site, attempt to assign the node to the specified site. If the specified node is the wrong type, doesn't exist, or is already used by another constrained node, the constraint is invalid so fail with an error.</li>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Example labeling for a subset of the netlist and device graphs</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table><p>
|
||||
The labeled nodes now need to be placed. The initial placement uses a simple greedy algorithm to create a valid (although not necessarily optimal or even routable) placement:</p><ol>
|
||||
<li>Loop over the cells in the netlist. If any cell has a LOC constraint, which locks the cell to a specific physical site, attempt to assign the node to the specified site. If the specified node is the wrong type, doesn't exist, or is already used by another constrained node, the constraint is invalid so fail with an error.</li>
|
||||
<li>Loop over all of the unconstrained cells in the netlist and assign them to the first unused site with the right label. If none are available, the design is too big for the device so fail with an error.</li>
|
||||
</ol><p>
|
||||
Once the design is placed, the placement optimizer then loops over the design and attempts to improve it. A simulated annealing algorithm is used, where changes to the design are accepted unconditionally if they make the placement better, and with a random, gradually decreasing probability if they make it worse. The optimizer terminates when the design receives a perfect score (indicating an optimal placement) or if it stops making progress for several iterations. Each iteration does the following:</p><ol><li>Compute a score for the current design based on the number of unroutable nets, the amount of routing congestion (number of nets crossing between halves of the device), and static timing analysis (not yet implemented, always zero).</li>
|
||||
Once the design is placed, the placement optimizer then loops over the design and attempts to improve it. A simulated annealing algorithm is used, where changes to the design are accepted unconditionally if they make the placement better, and with a random, gradually decreasing probability if they make it worse. The optimizer terminates when the design receives a perfect score (indicating an optimal placement) or if it stops making progress for several iterations. Each iteration does the following:</p><ol>
|
||||
<li>Compute a score for the current design based on the number of unroutable nets, the amount of routing congestion (number of nets crossing between halves of the device), and static timing analysis (not yet implemented, always zero).</li>
|
||||
<li>Make a list of nodes that contributed to this score in some way (having some attached nets unroutable, crossing to the other half of the device, or failing timing).</li>
|
||||
<li>Remove nodes from the list that are LOC'd to a specific location since we're not allowed to move them.</li>
|
||||
<li>Remove nodes from the list that have only one legal placement in the device (for example, oscillator hard IP) since there's nowhere else for them to go.</li>
|
||||
<li>Pick a node from the remainder of the list at random. Call this our pivot.</li>
|
||||
<li>Find a list of candidate placements for the pivot: </li>
|
||||
<ol><li>Consider all routable placements in the other half of the device.</li>
|
||||
<ol>
|
||||
<li>Consider all routable placements in the other half of the device.</li>
|
||||
<li>If none were found, consider all routable placements anywhere in the device.</li>
|
||||
<li>If none were found, consider all placements anywhere in the device even if they're not routable.</li>
|
||||
</ol><li>Pick one of the candidates at random and move the pivot to that location. If another cell in the netlist is already there, put it in the vacant site left by the pivot.</li>
|
||||
</ol>
|
||||
<li>Pick one of the candidates at random and move the pivot to that location. If another cell in the netlist is already there, put it in the vacant site left by the pivot.</li>
|
||||
<li>Re-compute the score for the design. If it's better, accept this change and start the next iteration.</li>
|
||||
<li>If the score is worse, accept it with a random probability which decreases as the iteration number goes up. If the change is not accepted, restore the previous placement.</li>
|
||||
</ol><p>
|
||||
After optimization, the design is checked for routability. If any edges in the netlist graph don't correspond to edges in the device graph, the user probably asked for something impossible (for example, trying to hook a flipflop's output to a comparator's reference voltage input) so fail with an error.</p><p> The design is then routed. This is quite simple due to the crossbar structure of the device. For each edge in the netlist:</p><ol><li>If dedicated (non-fabric) routing is used for this path, configure the destination's input mux appropriately and stop.</li>
|
||||
After optimization, the design is checked for routability. If any edges in the netlist graph don't correspond to edges in the device graph, the user probably asked for something impossible (for example, trying to hook a flipflop's output to a comparator's reference voltage input) so fail with an error.</p><p> The design is then routed. This is quite simple due to the crossbar structure of the device. For each edge in the netlist:</p><ol>
|
||||
<li>If dedicated (non-fabric) routing is used for this path, configure the destination's input mux appropriately and stop.</li>
|
||||
<li>If the source and destination are in the same half of the device, configure the destination's input mux appropriately and stop.</li>
|
||||
<li>A cross-connection must be used. Check if we already used one to bring the source signal to the other half of the device. If found, configure the destination to route from that cross-connection and stop.</li>
|
||||
<li>Check if we have any cross-connections left going in this direction. If they're all used, the design is unroutable due to congestion so fail with an error.</li>
|
||||
<li>Pick the next unused cross-connection and configure it to route from the source. Configure the destination to route from the cross-connection and stop.</li>
|
||||
</ol><p>
|
||||
Once routing is finished, run a series of post-PAR design rule checks. These currently include the following:</p><ul><li>If any node has no loads, generate a warning</li>
|
||||
Once routing is finished, run a series of post-PAR design rule checks. These currently include the following:</p><ul>
|
||||
<li>If any node has no loads, generate a warning</li>
|
||||
<li>If an I/O buffer is connected to analog hard IP, fail with an error if it's not configured in analog mode.</li>
|
||||
<li>Some signals (such as comparator inputs and oscillator power-down controls) are generated by a shared mux and fed to many loads. If different loads require conflicting settings for the shared mux, fail with an error.</li>
|
||||
</ul><p>
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
<div>
|
||||
|
||||
|
||||
<figure><div><p><img alt="Supporters of Republican presidential nominee Donald Trump cheer during election night at the New York Hilton Midtown in New York on November 9, 2016. / AFP / JIM WATSON (Photo credit should read JIM WATSON/AFP/Getty Images)" height="480" itemprop="image" src="http://media.breitbart.com/media/2016/11/GettyImages-621866810-640x480.jpg" width="640"></img></p><p>JIM WATSON/AFP/Getty Images</p>
|
||||
|
||||
<figure>
|
||||
<div><p><img itemprop="image" src="http://media.breitbart.com/media/2016/11/GettyImages-621866810-640x480.jpg" alt="Supporters of Republican presidential nominee Donald Trump cheer during election night at the New York Hilton Midtown in New York on November 9, 2016. / AFP / JIM WATSON (Photo credit should read JIM WATSON/AFP/Getty Images)" width="640" height="480"></p><p>JIM WATSON/AFP/Getty Images</p>
|
||||
</div>
|
||||
</figure> <time datetime="2016-12-22T10:43:37Z">22 Dec, 2016</time><time datetime="2016-12-22T18:59:12Z">22 Dec, 2016</time></div><div>
|
||||
</figure>
|
||||
<time datetime="2016-12-22T10:43:37Z">22 Dec, 2016</time>
|
||||
<time datetime="2016-12-22T18:59:12Z">22 Dec, 2016</time>
|
||||
</div><div>
|
||||
|
||||
|
||||
<div id="EmailOptin">
|
||||
<p><span>SIGN UP</span> FOR OUR NEWSLETTER</p>
|
||||
|
@ -15,7 +21,7 @@
|
|||
<p><span>SIGN UP</span> FOR OUR NEWSLETTER</p>
|
||||
|
||||
</div>
|
||||
<p><span>The tweet from Vulture magazine reads, “</span><a href="https://twitter.com/hashtag/Hamilton?src=hash" rel="noopener" target="_blank"><span>#Hamilton</span></a><span> Chicago show interrupted by angry Trump supporter.” Emery retweeted the story, saying, “Are there un-angry Trump supporters?”</span></p>
|
||||
<p><span>The tweet from Vulture magazine reads, “</span><a href="https://twitter.com/hashtag/Hamilton?src=hash" target="_blank" rel="noopener"><span>#Hamilton</span></a><span> Chicago show interrupted by angry Trump supporter.” Emery retweeted the story, saying, “Are there un-angry Trump supporters?”</span></p>
|
||||
|
||||
|
||||
|
||||
|
@ -33,7 +39,7 @@
|
|||
|
||||
|
||||
<p><span>Facebook believe that Emery, along with other Snopes writers, ABC News, and </span><a href="http://www.breitbart.com/tech/2016/12/16/flashback-weekly-standard-data-shows-politifact-has-it-out-for-republicans/"><span>Politifact</span></a><span> are impartial enough to label and silence what they believe to be “fake news” on social media. </span></p>
|
||||
<p><i><span>Lucas Nolan is a reporter for Breitbart Tech covering issues of free speech and online censorship. Follow him on Twitter </span></i><a href="http://twitter.com/lucasnolan_" rel="noopener" target="_blank"><i><span>@LucasNolan_</span></i></a><i><span> or email him at </span></i><a href="http://www.breitbart.com/wp-admin/blank"><i><span>lnolan@breitbart.com</span></i></a></p>
|
||||
<p><i><span>Lucas Nolan is a reporter for Breitbart Tech covering issues of free speech and online censorship. Follow him on Twitter </span></i><a href="http://twitter.com/lucasnolan_" target="_blank" rel="noopener"><i><span>@LucasNolan_</span></i></a><i><span> or email him at </span></i><a href="http://www.breitbart.com/wp-admin/blank"><i><span>lnolan@breitbart.com</span></i></a></p>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div id="gigya-share-btns-2_gig_containerParent" itemprop="articleBody">
|
||||
<div itemprop="articleBody" id="gigya-share-btns-2_gig_containerParent">
|
||||
<p>Most people go to hotels for the pleasure of sleeping in a giant bed with clean white sheets and waking up to fresh towels in the morning.</p>
|
||||
|
||||
<p>But those towels and sheets might not be as clean as they look, according to the hotel bosses that responded to an online thread about the things hotel owners don’t want you to know.</p>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<div>
|
||||
<div>
|
||||
|
||||
<p><img alt="bandb2.jpg" height="423" src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/18/10/bandb2.jpg" title="bandb2.jpg" width="564"></img></p>
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/18/10/bandb2.jpg" alt="bandb2.jpg" title="bandb2.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
@ -37,7 +37,7 @@
|
|||
<div>
|
||||
<div>
|
||||
|
||||
<p><img alt="hotel-door-getty.jpg" height="423" src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/05/26/11/hotel-door-getty.jpg" title="hotel-door-getty.jpg" width="564"></img></p>
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/05/26/11/hotel-door-getty.jpg" alt="hotel-door-getty.jpg" title="hotel-door-getty.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
@ -52,12 +52,9 @@
|
|||
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<p><img alt="luggage-3.jpg" height="423" src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2013/07/31/15/luggage-3.jpg" title="luggage-3.jpg" width="564"></img></p>
|
||||
|
||||
</div>
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2013/07/31/15/luggage-3.jpg" alt="luggage-3.jpg" title="luggage-3.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -70,7 +67,7 @@
|
|||
<div>
|
||||
<div>
|
||||
|
||||
<p><img alt="Lifestyle-hotels.jpg" height="423" src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/04/13/11/Lifestyle-hotels.jpg" title="Lifestyle-hotels.jpg" width="564"></img></p>
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2015/04/13/11/Lifestyle-hotels.jpg" alt="Lifestyle-hotels.jpg" title="Lifestyle-hotels.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
@ -91,20 +88,12 @@
|
|||
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<div data-scald-gallery="3739501">
|
||||
|
||||
<h2><span></span>Business news in pictures</h2>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>6. Mini bars almost always lose money</h3>
|
||||
|
||||
<p>Despite the snacks in the minibar seeming like the most overpriced food you have ever seen, hotel owners are still struggling to make a profit from those snacks. "Minibars almost always lose money, even when they charge $10 for a Diet Coke,” Sharon said.</p>
|
||||
|
@ -114,7 +103,7 @@
|
|||
<div>
|
||||
<div>
|
||||
|
||||
<p><img alt="agenda7.jpg" height="423" src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/13/16/agenda7.jpg" title="agenda7.jpg" width="564"></img></p>
|
||||
<p><img src="https://static.independent.co.uk/s3fs-public/styles/story_medium/public/thumbnails/image/2014/03/13/16/agenda7.jpg" alt="agenda7.jpg" title="agenda7.jpg" width="564" height="423"></p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
@ -126,11 +115,14 @@
|
|||
<p>7. Always made sure the hand towels are clean when you arrive</p>
|
||||
|
||||
<p>Forrest Jones made a discovery when he was helping out with the housekeepers. “You know where you almost always find a hand towel in any recently-vacated hotel room that was occupied by a guy? On the floor, next to the bed, about halfway down, maybe a little toward the foot of the bed. Same spot in the floor, next to almost every bed occupied by a man, in every room. I'll leave the rest to your imagination,” he said.</p>
|
||||
<meta content="2016-05-08T10:11:51+01:00" itemprop="datePublished"></meta><ul><li>
|
||||
<meta itemprop="datePublished" content="2016-05-08T10:11:51+01:00">
|
||||
<ul>
|
||||
<li>
|
||||
More about:
|
||||
</li>
|
||||
<li><a href="http://fakehost/topic/Hotels" itemprop="keywords">Hotels</a></li>
|
||||
<li><a href="http://fakehost/topic/Hygiene" itemprop="keywords">Hygiene</a></li>
|
||||
<li><a itemprop="keywords" href="http://fakehost/topic/Hotels">Hotels</a></li>
|
||||
<li><a itemprop="keywords" href="http://fakehost/topic/Hygiene">Hygiene</a></li>
|
||||
</ul>
|
||||
<p><a href="http://fakehost/syndication/reuse-permision-form?url=http://www.independent.co.uk/news/business/news/seven-secrets-that-hotel-owners-dont-want-you-to-know-10506160.html" target="_blank"><img src="http://fakehost/sites/all/themes/ines_themes/independent_theme/img/reuse.png" width="25"></img>Reuse content</a>
|
||||
|
||||
<p><a href="http://fakehost/syndication/reuse-permision-form?url=http://www.independent.co.uk/news/business/news/seven-secrets-that-hotel-owners-dont-want-you-to-know-10506160.html" target="_blank"><img src="http://fakehost/sites/all/themes/ines_themes/independent_theme/img/reuse.png" width="25">Reuse content</a>
|
||||
</p></div>
|
File diff suppressed because one or more lines are too long
|
@ -14,20 +14,18 @@
|
|||
<div id="superlist_3758406_5547140" rel:buzz_num="3">
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p><img height="412" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" width="203"></img></p>
|
||||
<p><img src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608056-15.jpg" height="412" width="203"></p>
|
||||
</div>
|
||||
<p>Facebook</p>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<p><img height="412" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" width="412"></img></p>
|
||||
<p><img src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" rel:bf_image_src="http://ak-hdl.buzzfed.com/static/2015-04/21/5/enhanced/webdr12/grid-cell-2501-1429608057-18.jpg" height="412" width="412"></p>
|
||||
</div>
|
||||
<p>Facebook</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="superlist_3758406_5547284" rel:buzz_num="4">
|
||||
<p>West Mercia police <a href="https://www.westmercia.police.uk/article/9500/Warning-Issued-As-Shrewsbury-Woman-Dies-After-Taking-Suspected-Diet-Pills">said the tablets were believed to contain dinitrophenol</a>, known as DNP, which is a highly toxic industrial chemical. </p>
|
||||
<p>“We are undoubtedly concerned over the origin and sale of these pills and are working with partner agencies to establish where they were bought from and how they were advertised,” said chief inspector Jennifer Mattinson from the West Mercia police.</p>
|
||||
|
@ -36,6 +34,7 @@
|
|||
</div>
|
||||
<div id="superlist_3758406_5547219" rel:buzz_num="5">
|
||||
<h2>Fiona Parry issued a plea for people to stay away from pills containing the chemical.</h2>
|
||||
|
||||
<p>“[Eloise] just never really understood how dangerous the tablets that she took were,” she said. “Most of us don’t believe that a slimming tablet could possibly kill us.</p>
|
||||
<p>“DNP is not a miracle slimming pill. It is a deadly toxin.”</p>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<div>
|
||||
<div>
|
||||
<h3>Study Webtext</h3>
|
||||
<h2><span color="Maroon
 " face="Lucida Handwriting ">"Bartleby the Scrivener: A Story of Wall-Street " </span>(1853) <br></br>
|
||||
<h2><span face="Lucida Handwriting " color="Maroon
|
||||
">"Bartleby the Scrivener: A Story of Wall-Street " </span>(1853) <br>
|
||||
Herman Melville</h2>
|
||||
<h2><a href="http://www.vcu.edu/engweb/webtexts/bartleby.html
 " target="_blank "><img alt="To the story text without notes
 " height="38 " src="http://fakehost/test/hmhome.gif " width="38 "></img></a>
|
||||
<h2><a href="http://www.vcu.edu/engweb/webtexts/bartleby.html" target="_blank "><img src="http://fakehost/test/hmhome.gif" alt="To the story text without notes
|
||||
" height="38 " width="38 "></a>
|
||||
</h2>
|
||||
<h3>Prepared by <a href="http://www.vcu.edu/engweb">Ann
|
||||
Woodlief,</a> Virginia Commonwealth University</h3>
|
||||
|
@ -1383,4 +1384,4 @@
|
|||
</p>
|
||||
<p> Ah
|
||||
Bartleby! Ah humanity!</p>
|
||||
</div></div>
|
||||
</div>
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Author": null,
|
||||
"Author": "por \n \n \n César Salza",
|
||||
"Direction": null,
|
||||
"Excerpt": "Twitter Lite llega a 11 países de América Latina, para ayudar a los usuarios con mala señal de sus redes móviles.",
|
||||
"Image": "https:\/\/cdn1.cnet.com\/img\/JumVcu1ZSLtPP8ui0UWaSlgi5RU=\/670x503\/2017\/12\/01\/b36ce794-e0b8-495c-a198-184923a8f4e9\/twitter-lite.jpg",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Author": "Steven Musil",
|
||||
"Author": "by \n\n \n Steven Musil\n \n\n\n January 18, 2017 11:00 PM PST\n \n \n \n \n \n \n\n \n @stevenmusil",
|
||||
"Direction": null,
|
||||
"Excerpt": "Facebook CEO says be a friend and have a shared vision, but scare them when you have to and move fast.",
|
||||
"Image": "https:\/\/cnet3.cbsistatic.com\/img\/1JaRRjqhoGxDVkFxTRRWkZgyK2Q=\/670x503\/2014\/03\/21\/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e\/mark-zuckerberg-facebook-home-10671610x407.jpg",
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
<div data-component="lazyloadImages" itemprop="articleBody">
|
||||
<div itemprop="articleBody" data-component="lazyloadImages">
|
||||
|
||||
|
||||
|
||||
|
||||
<figure section="shortcodeImage"><span><span itemprop="image" itemscope="" itemtype="https://schema.org/ImageObject"><img alt="" class="" height="0" src="https://cnet1.cbsistatic.com/img/nAMdBzIE1ogVw5bOBZBaiJCt3Ro=/570x0/2014/03/21/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e/mark-zuckerberg-facebook-home-10671610x407.jpg" width="570"></img><meta content="https://cnet1.cbsistatic.com/img/nAMdBzIE1ogVw5bOBZBaiJCt3Ro=/570x0/2014/03/21/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e/mark-zuckerberg-facebook-home-10671610x407.jpg" itemprop="url"></meta><meta content="0" itemprop="height"></meta><meta content="570" itemprop="width"></meta></span></span>
|
||||
<figure section="shortcodeImage"><span><span itemprop="image" itemscope itemtype="https://schema.org/ImageObject"><img src="https://cnet1.cbsistatic.com/img/nAMdBzIE1ogVw5bOBZBaiJCt3Ro=/570x0/2014/03/21/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e/mark-zuckerberg-facebook-home-10671610x407.jpg" class alt width="570" height="0"><meta itemprop="url" content="https://cnet1.cbsistatic.com/img/nAMdBzIE1ogVw5bOBZBaiJCt3Ro=/570x0/2014/03/21/863df5d9-e8b8-4b38-851b-5e3f77f2cf0e/mark-zuckerberg-facebook-home-10671610x407.jpg"><meta itemprop="height" content="0"><meta itemprop="width" content="570"></span></span>
|
||||
<figcaption><span><p>Facebook CEO Mark Zuckerberg, the man with the acquisition plan.</p></span><span>Photo by James Martin/CNET
|
||||
</span></figcaption></figure><p>Anyone who has ever been involved in closing a billion-dollar acquisition deal will tell you that you don't go in without a clear, well thought out plan.</p>
|
||||
</span></figcaption>
|
||||
</figure>
|
||||
<p>Anyone who has ever been involved in closing a billion-dollar acquisition deal will tell you that you don't go in without a clear, well thought out plan.</p>
|
||||
|
||||
<p>Facebook CEO Mark Zuckerberg knows a thing or two about how to seal the deal on blockbuster buys. After all, he's the man behind his company's <a href="https://www.cnet.com/news/facebook-closes-19-billion-deal-for-whatsapp/" target="_blank">$19 billion acquisition</a> of WhatsApp, he <a href="https://www.cnet.com/news/zuckerberg-did-1-billion-instagram-deal-on-his-own/" target="_blank">personally brokered</a> its $1 billion buyout of <a href="https://www.cnet.com/news/why-facebook-plunked-down-1-billion-to-buy-instagram/" target="_blank">Instagram</a> and closed the <a href="https://www.cnet.com/news/facebook-to-buy-oculus-for-2-billion/" target="_blank">$3 billion deal</a> to buy Oculus VR.</p>
|
||||
<p>Zuckerberg offered a primer on the strategies he and his company employ when they see an attractive target during testimony Tuesday <a href="https://www.cnet.com/news/zenimax-sues-oculus-over-virtual-reality-rift-tech/">in a lawsuit with ZeniMax Media</a>, which accuses Oculus and Facebook of "misappropriating" trade secrets and copyright infringement. At the heart of the lawsuit is technology that helped create liftoff for virtual reality, one of the <a data-component="externalLink" href="http://www.cbsnews.com/videos/the-reality-of-the-virtual-world/" target="_blank">hottest gadget trends today.</a></p>
|
||||
<p>A key Facebook approach is building a long-term relationship with your target, Zuckerberg said at the trial. These deals don't just pop up over night, he said according to a transcript reviewed by <a data-component="externalLink" href="http://www.businessinsider.com/mark-zuckerberg-explains-facebooks-acquisition-strategy-2017-1" target="_blank">Business Insider</a>. They take time to cultivate. </p>
|
||||
<p>Zuckerberg offered a primer on the strategies he and his company employ when they see an attractive target during testimony Tuesday <a href="https://www.cnet.com/news/zenimax-sues-oculus-over-virtual-reality-rift-tech/">in a lawsuit with ZeniMax Media</a>, which accuses Oculus and Facebook of "misappropriating" trade secrets and copyright infringement. At the heart of the lawsuit is technology that helped create liftoff for virtual reality, one of the <a href="http://www.cbsnews.com/videos/the-reality-of-the-virtual-world/" target="_blank" data-component="externalLink">hottest gadget trends today.</a></p>
|
||||
<p>A key Facebook approach is building a long-term relationship with your target, Zuckerberg said at the trial. These deals don't just pop up over night, he said according to a transcript reviewed by <a href="http://www.businessinsider.com/mark-zuckerberg-explains-facebooks-acquisition-strategy-2017-1" target="_blank" data-component="externalLink">Business Insider</a>. They take time to cultivate. </p>
|
||||
<blockquote>
|
||||
<p>I've been building relationships, at least in Instagram and the WhatsApp cases, for years with the founders and the people that are involved in these companies, which made [it] so that when it became time or when we thought it was the right time to move, we felt like we had a good amount of context and had good relationships so that we could move quickly, which was competitively important and why a lot of these acquisitions, I think, came to us instead of our competitors and ended up being very good acquisitions over time that a lot of competitors wished they had gotten instead. </p>
|
||||
</blockquote>
|
||||
|
@ -32,7 +34,7 @@
|
|||
|
||||
|
||||
|
||||
<p><em><strong>Tech Enabled:</strong> CNET chronicles tech's role in providing new kinds of accessibility. Check it out <a href="https://www.cnet.com/tech-enabled/">here</a>.</em><em><strong><br></br></strong></em></p>
|
||||
<p><em><strong>Tech Enabled:</strong> CNET chronicles tech's role in providing new kinds of accessibility. Check it out <a href="https://www.cnet.com/tech-enabled/">here</a>.</em><em><strong><br></strong></em></p>
|
||||
<p><em><strong>Technically Literate:</strong> Original works of short fiction with unique perspectives on tech, exclusively on CNET. <a href="https://www.cnet.com/technically-literate/">Here</a>.</em></p>
|
||||
|
||||
|
||||
|
@ -40,4 +42,5 @@
|
|||
|
||||
|
||||
|
||||
|
||||
</div>
|
|
@ -6,10 +6,11 @@
|
|||
|
||||
<p> The report assessed poverty levels, income and wealth inequality, economic mobility and unemployment levels among 10 wealthy countries with social welfare programs. </p>
|
||||
<div id="smartassetcontainer">
|
||||
<div>
|
||||
<div>
|
||||
<div id="smartasset-article">
|
||||
<div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
Powered by SmartAsset.com
|
||||
</p>
|
||||
|
@ -19,10 +20,6 @@
|
|||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p> Among its key findings: the class you're born into matters much more in the U.S. than many of the other countries. </p>
|
||||
<p> As the <a href="http://web.stanford.edu/group/scspi-dev/cgi-bin/publications/state-union-report" target="_blank">report states</a>: "[T]he birth lottery matters more in the U.S. than in most well-off countries." </p>
|
||||
|
@ -32,7 +29,7 @@
|
|||
|
||||
<p> The report also suggested the U.S. might not be the "jobs machine" it thinks it is, when compared to other countries. </p>
|
||||
<p> It ranked near the bottom of the pack based on the levels of unemployment among men and women of prime working age. The study determined this by taking the ratio of employed men and women between the ages of 25 and 54 compared to the total population of each country. </p>
|
||||
<p> The overall rankings of the countries were as follows:<span> <br></br>1. Finland <span> <br></br>2. Norway<span> <br></br>3. Australia <span> <br></br>4. Canada<span> <br></br>5. Germany<span> <br></br>6. France<span> <br></br>7. United Kingdom <span> <br></br>8. Italy<span> <br></br>9. Spain<span> <br></br>10. United States </span></span>
|
||||
<p> The overall rankings of the countries were as follows:<span> <br>1. Finland <span> <br>2. Norway<span> <br>3. Australia <span> <br>4. Canada<span> <br>5. Germany<span> <br>6. France<span> <br>7. United Kingdom <span> <br>8. Italy<span> <br>9. Spain<span> <br>10. United States </span></span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
<div id="Box">
|
||||
|
||||
|
||||
|
||||
<div id="Main">
|
||||
<div>
|
||||
|
||||
<h2>About This Site</h2>
|
||||
<p>Daring Fireball is written and produced by John Gruber.</p>
|
||||
<p>
|
||||
<a href="http://fakehost/graphics/author/addison-bw.jpg"> <img alt="Photograph of the author." src="http://fakehost/graphics/author/addison-bw-425.jpg"></img></a>
|
||||
<br></br><em>Portrait by <a href="http://superbiate.com/inquiries/">George Del Barrio</a></em> </p>
|
||||
<a href="http://fakehost/graphics/author/addison-bw.jpg"> <img src="http://fakehost/graphics/author/addison-bw-425.jpg" alt="Photograph of the author."></a>
|
||||
<br><em>Portrait by <a href="http://superbiate.com/inquiries/">George Del Barrio</a></em> </p>
|
||||
<h2>Mac Apps</h2>
|
||||
<ul><li><a href="http://www.barebones.com/products/bbedit/">BBEdit</a></li>
|
||||
<ul>
|
||||
<li><a href="http://www.barebones.com/products/bbedit/">BBEdit</a></li>
|
||||
<li><a href="http://www.flyingmeat.com/acorn/">Acorn</a></li>
|
||||
<li><a href="http://www.red-sweater.com/marsedit/">MarsEdit</a></li>
|
||||
<li><a href="http://aged-and-distilled.com/napkin/">Napkin</a></li>
|
||||
|
@ -19,9 +15,12 @@
|
|||
<li><a href="http://latenightsw.com/sd4/index.html">Script Debugger</a></li>
|
||||
<li><a href="http://www.ambrosiasw.com/utilities/snapzprox/">Snapz Pro X</a></li>
|
||||
<li><a href="http://nightly.webkit.org/">WebKit</a></li>
|
||||
</ul><h2>iPhone Apps</h2>
|
||||
<ul><li><a href="http://vesperapp.co/">Vesper</a></li>
|
||||
</ul><h2>Server Software</h2>
|
||||
</ul>
|
||||
<h2>iPhone Apps</h2>
|
||||
<ul>
|
||||
<li><a href="http://vesperapp.co/">Vesper</a></li>
|
||||
</ul>
|
||||
<h2>Server Software</h2>
|
||||
<p>The Daring Fireball website is hosted by <a href="http://joyent.com/">Joyent</a>.</p>
|
||||
<p>Articles and links are published through <a href="http://movabletype.org/">Movable Type</a>. In addition to my own SmartyPants and Markdown plug-ins, Daring Fireball uses several excellent Movable Type plug-ins, including Brad Choate’s <a href="http://bradchoate.com/weblog/2003/06/24/regular-expressions">MT-Regex</a> and <a href="http://bradchoate.com/weblog/2004/10/20/mtifempty">MT-IfEmpty</a>, and <a href="http://bumppo.net/projects/amputator/">Nat Irons’s Amputator</a>.</p>
|
||||
<p>Stats are tracked using <a href="http://haveamint.com/">Mint</a>. Additional web nerdery, including the membership system, is fueled by <a href="http://perl.org/">Perl</a>, <a href="http://www.php.net/">PHP</a>, and <a href="http://www.mysql.com/">MySQL</a>.</p>
|
||||
|
@ -29,10 +28,3 @@
|
|||
<p>Web standards are important, and Daring Fireball adheres to them. Specifically, Daring Fireball’s HTML markup should validate as either <a href="http://www.whatwg.org/specs/web-apps/current-work/">HTML 5</a> or XHTML 4.01 Transitional, its layout is constructed using <a href="http://jigsaw.w3.org/css-validator/validator?uri=http://daringfireball.net/css/fireball_screen.css">valid CSS</a>, and its syndicated feed is <a href="http://feedvalidator.org/check?url=http%3A%2F%2Fdaringfireball.net%2Findex.xml">valid Atom</a>.</p>
|
||||
<p>If Daring Fireball looks goofy in your browser, you’re likely using a shitty browser that doesn’t support web standards. Internet Explorer, I’m looking in your direction. If you complain about this, I will laugh at you, because I do not care. If, however, you are using a modern, standards-compliant browser and have trouble viewing or reading Daring Fireball, please do let me know.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1,4 +1,5 @@
|
|||
<article>
|
||||
<h2>Lorem</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
@ -8,11 +9,11 @@
|
|||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
<p>Images</p>
|
||||
<p><img src="https://test/foo/bar/src.jpg"></img></p>
|
||||
<p><img data-original="https://test/foo/bar/data-original.jpg" src="https://test/foo/bar/data-original.jpg"></img></p>
|
||||
<p><img data-orig="https://test/foo/bar/data-orig.jpg" src="https://test/foo/bar/data-orig.jpg"></img></p>
|
||||
<p><img data-url="https://test/foo/bar/data-url.jpg" src="https://test/foo/bar/data-url.jpg"></img></p>
|
||||
<p><img data-src="https://test/foo/bar/data-src.jpg" src="https://test/foo/bar/data-src.jpg"></img></p>
|
||||
<p><img src="https://test/foo/bar/src.jpg"></p>
|
||||
<p><img data-original="https://test/foo/bar/data-original.jpg" src="https://test/foo/bar/data-original.jpg"></p>
|
||||
<p><img data-orig="https://test/foo/bar/data-orig.jpg" src="https://test/foo/bar/data-orig.jpg"></p>
|
||||
<p><img data-url="https://test/foo/bar/data-url.jpg" src="https://test/foo/bar/data-url.jpg"></p>
|
||||
<p><img data-src="https://test/foo/bar/data-src.jpg" src="https://test/foo/bar/data-src.jpg"></p>
|
||||
<p>
|
||||
Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
|
|
|
@ -2,15 +2,20 @@
|
|||
<header>
|
||||
|
||||
|
||||
</header><div>
|
||||
|
||||
</header>
|
||||
<div>
|
||||
<p>Glass cloche terrariums are not only appealing to the eye, but they also preserve a bit of nature in your home and serve as a simple, yet beautiful, piece of art. Closed terrariums are easy to care for, as they retain much of their own moisture and provide a warm environment with a consistent level of humidity. You won’t have to water the terrariums unless you see that the walls are not misting up. Small growing plants that don’t require a lot of light work best such as succulents, ferns, moss, even orchids.</p>
|
||||
<figure><img alt="Glass cloche terrariums" data-credit="Lucy Akins " longdesc="http://s3.amazonaws.com/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg" src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg" title="Glass cloche terrariums"></img></figure><figcaption> Glass cloche terrariums (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg" alt="Glass cloche terrariums" title="Glass cloche terrariums" data-credit="Lucy Akins " longdesc="http://s3.amazonaws.com/photography.prod.demandstudios.com/16149374-814f-40bc-baf3-ca20f149f0ba.jpg"> </figure>
|
||||
<figcaption> Glass cloche terrariums (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div id="relatedContentUpper" data-module="rcp_top">
|
||||
<header class>
|
||||
<h3>Other People Are Reading</h3> </header>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>What You'll Need:</span></p><ul><li>Cloche</li>
|
||||
</div>
|
||||
<div> <p><span>What You'll Need:</span></p><ul>
|
||||
<li>Cloche</li>
|
||||
<li>Planter saucer, small shallow dish or desired platform</li>
|
||||
<li>Floral foam oasis</li>
|
||||
<li>Ruler </li>
|
||||
|
@ -20,75 +25,78 @@
|
|||
<li>Moss</li>
|
||||
<li>Tweezers</li>
|
||||
<li>Other small decorative items (optional)</li>
|
||||
</ul></div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 1</span></p><p>Measure the circumference of your cloche and cut the foam oasis about 3/4 inch (2 cm) smaller. Place the foam oasis into a container full of water and allow to soak until it sinks to the bottom. Dig out a hole on the oasis large enough to fit your plant, being careful not to pierce all the way through to the bottom.</p>
|
||||
</div>
|
||||
<figure><img alt="Dig a hole in the oasis." data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/fc249ef6-4d27-41b4-8c21-15f7a8512b50.jpg"></img></figure><figcaption> Dig a hole in the oasis. (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/fc249ef6-4d27-41b4-8c21-15f7a8512b50.jpg" alt="Dig a hole in the oasis." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Dig a hole in the oasis. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 2</span></p><p>Insert your plant into the hole.</p>
|
||||
</div>
|
||||
<figure><img alt="Orchid in foam oasis" data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/aae11d4d-a4aa-4251-a4d9-41023ebf6d84.jpg"></img></figure><figcaption> Orchid in foam oasis (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/aae11d4d-a4aa-4251-a4d9-41023ebf6d84.jpg" alt="Orchid in foam oasis" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Orchid in foam oasis (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 3</span></p><p>You can add various plants if you wish.</p>
|
||||
</div>
|
||||
<figure><img alt="Various foliage" data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/7afdfa1e-da74-44b5-b89c-ca8123516272.jpg"></img></figure><figcaption> Various foliage (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/7afdfa1e-da74-44b5-b89c-ca8123516272.jpg" alt="Various foliage" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Various foliage (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 4</span></p><p>Using floral pins, attach enough moss around the oasis to cover it.</p>
|
||||
</div>
|
||||
<figure><img alt="Attach moss." data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/4f6612c0-316a-4c74-bb03-cb4e778f6d72.jpg"></img></figure><figcaption> Attach moss. (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/4f6612c0-316a-4c74-bb03-cb4e778f6d72.jpg" alt="Attach moss." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Attach moss. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 5</span></p><p>Gently place the cloche over the oasis. The glass may push some of the moss upward, exposing some of the foam.</p>
|
||||
</div>
|
||||
<figure><img alt="Place cloche over oasis." data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/eeb1e0b4-e573-40a3-8db1-2c76f0b13b84.jpg"></img></figure><figcaption> Place cloche over oasis. (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/eeb1e0b4-e573-40a3-8db1-2c76f0b13b84.jpg" alt="Place cloche over oasis." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Place cloche over oasis. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 6</span></p><p>Simply pull down the moss with tweezers or insert more moss to fill in the empty spaces.</p>
|
||||
</div>
|
||||
<figure><img alt="Rearrange moss." data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/812d4649-4152-4363-97c0-f181d02e709a.jpg"></img></figure><figcaption> Rearrange moss. (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/812d4649-4152-4363-97c0-f181d02e709a.jpg" alt="Rearrange moss." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Rearrange moss. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 7</span></p><p>You can use any platform you wish. In this case, a small saucer was used.</p>
|
||||
</div>
|
||||
<figure><img alt="Place cloche on a platform to sit on." data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/0cb3988c-9318-47d6-bc9c-c798da1ede72.jpg"></img></figure><figcaption> Place cloche on a platform to sit on. (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/default/cme/photography.prod.demandstudios.com/0cb3988c-9318-47d6-bc9c-c798da1ede72.jpg" alt="Place cloche on a platform to sit on." data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Place cloche on a platform to sit on. (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 8</span></p><p>This particular terrarium rests on a planter saucer and features a small white pumpkin.</p>
|
||||
</div>
|
||||
<figure><img alt="Cloche placed on a terracotta saucer" data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/e3e18f0b-ab2c-4ffb-9988-a1ea63faef8b.jpg"></img></figure><figcaption> Cloche placed on a terracotta saucer (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/e3e18f0b-ab2c-4ffb-9988-a1ea63faef8b.jpg" alt="Cloche placed on a terracotta saucer" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Cloche placed on a terracotta saucer (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Step 9</span></p><p>This particular terrarium was placed on a wood slice and a little toy squirrel was placed inside to add a little whimsy.</p>
|
||||
</div>
|
||||
<figure><img alt="Placed on a wooden slice" data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/2cd79f8d-0d16-4573-8861-e47fb74b0638.jpg"></img></figure><figcaption> Placed on a wooden slice (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/2cd79f8d-0d16-4573-8861-e47fb74b0638.jpg" alt="Placed on a wooden slice" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Placed on a wooden slice (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div> <p><span>Finished Terrarium</span></p><p>Displayed alone or in a group, these pretty arrangements allow you to add a little nature to your decor or tablescape.</p>
|
||||
</div>
|
||||
<figure><img alt="Cloche terrarium" data-credit="Lucy Akins" src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/78670312-8636-4c42-a75c-3029f7aa6c73.jpg"></img></figure><figcaption> Cloche terrarium (Lucy Akins) </figcaption></div>
|
||||
<figure> <img src="http://img-aws.ehowcdn.com/640/cme/photography.prod.demandstudios.com/78670312-8636-4c42-a75c-3029f7aa6c73.jpg" alt="Cloche terrarium" data-credit="Lucy Akins"> </figure>
|
||||
<figcaption> Cloche terrarium (Lucy Akins) </figcaption>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<section data-module="rcp_tombstone" id="FeaturedTombstone"><h2>Featured</h2>
|
||||
|
||||
</section></div>
|
||||
|
||||
<section id="FeaturedTombstone" data-module="rcp_tombstone">
|
||||
<h2>Featured</h2>
|
||||
|
||||
</section>
|
||||
</div>
|
|
@ -1,58 +1,68 @@
|
|||
<section data-page-id="inlinetemplate" data-section="body" id="Body">
|
||||
|
||||
<header>
|
||||
<div data-type="AuthorProfile">
|
||||
<div>
|
||||
<p><a href="http://fakehost/contributor/gina_robertsgrey/" id="img-follow-tip" target="_top">
|
||||
<img data-failover="//img-aws.ehowcdn.com/60x60/ehow-cdn-assets/test15/media/images/authors/missing-author-image.png" onerror="var failover = this.getAttribute('data-failover');
 if (failover) failover = failover.replace(/^https?:/,'');
 var src = this.src ? this.src.replace(/^https?:/,'') : '';
 if (src != failover){
 this.src = failover;
 }" src="http://img-aws.ehowcdn.com/60x60/cme/cme_public_images/www_demandstudios_com/sitelife.studiod.com/ver1.0/Content/images/store/9/2/d9dd6f61-b183-4893-927f-5b540e45be91.Small.jpg"></img></a></p>
|
||||
<p><a id="img-follow-tip" href="http://fakehost/contributor/gina_robertsgrey/" target="_top">
|
||||
<img src="http://img-aws.ehowcdn.com/60x60/cme/cme_public_images/www_demandstudios_com/sitelife.studiod.com/ver1.0/Content/images/store/9/2/d9dd6f61-b183-4893-927f-5b540e45be91.Small.jpg" data-failover="//img-aws.ehowcdn.com/60x60/ehow-cdn-assets/test15/media/images/authors/missing-author-image.png" onerror="var failover = this.getAttribute('data-failover');
|
||||
if (failover) failover = failover.replace(/^https?:/,'');
|
||||
var src = this.src ? this.src.replace(/^https?:/,'') : '';
|
||||
if (src != failover){
|
||||
this.src = failover;
|
||||
}"> </a></p>
|
||||
</div>
|
||||
|
||||
<p><time datetime="2016-09-14T07:07:00-04:00" itemprop="dateModified">Last updated September 14, 2016</time></p>
|
||||
<p><time datetime="2016-09-14T07:07:00-04:00" itemprop="dateModified">Last updated September 14, 2016</time>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</header><div>
|
||||
<article data-type="article"><div>
|
||||
</div><div>
|
||||
<article data-type="article">
|
||||
<div>
|
||||
<div>
|
||||
<p>Graduation parties are a great way to commemorate the years of hard work teens and college co-eds devote to education. They’re also costly for mom and dad.</p>
|
||||
<p>The average cost of a graduation party in 2013 was a whopping $1,200, according to Graduationparty.com; $700 of that was allocated for food. However that budget was based on Midwestern statistics, and parties in urban areas like New York City are thought to have a much higher price tag.</p>
|
||||
<p>Thankfully, there are plenty of creative ways to trim a little grad party fat without sacrificing any of the fun or celebratory spirit.</p>
|
||||
</div>
|
||||
<figure><img alt="Graduation" data-credit="Mike Watson Images/Moodboard/Getty " data-pin-ehow-hover="true" data-pin-no-hover="true" longdesc="http://s3.amazonaws.com/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" title="Graduation"></img></figure><figcaption>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" alt="Graduation" title="Graduation" data-credit="Mike Watson Images/Moodboard/Getty " longdesc="http://s3.amazonaws.com/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/2F/86/5547EF62-EAF5-4256-945D-0496F61C862F/5547EF62-EAF5-4256-945D-0496F61C862F.jpg" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
(Mike Watson Images/Moodboard/Getty)
|
||||
</figcaption></div>
|
||||
</figcaption>
|
||||
</div>
|
||||
|
||||
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Parties hosted at restaurants, clubhouses and country clubs eliminate the need to spend hours cleaning up once party guests have gone home. But that convenience comes with a price tag. A country club may charge as much as $2,000 for room rental and restaurant food and beverage will almost always cost more than food prepped and served at home.</p></span> </p>
|
||||
<figure><img alt="Save money hosting the party at home." data-credit="Thomas Jackson/Digital Vision/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/FE/CB/121569D2-6984-4B2F-83C4-9D2D9A27CBFE/121569D2-6984-4B2F-83C4-9D2D9A27CBFE.jpg"></img></figure><figcaption>
|
||||
Thomas Jackson/Digital Vision/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/FE/CB/121569D2-6984-4B2F-83C4-9D2D9A27CBFE/121569D2-6984-4B2F-83C4-9D2D9A27CBFE.jpg" alt="Save money hosting the party at home." data-credit="Thomas Jackson/Digital Vision/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Thomas Jackson/Digital Vision/Getty Images </figcaption>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Instead of hiring a DJ, use your iPod or Smartphone to spin the tunes. Both easily hook up to most speakers or mp3 compatible docks to play music from your music library. Or download Pandora, the free online radio app, and play hours of music for free.</p>
|
||||
<p>Personalize the music with a playlist of the grad’s favorite songs or songs that were big hits during his or her years in school.</p></span> </p>
|
||||
<figure><img alt="Online radio can take the place of a hired DJ." data-credit="Spencer Platt/Getty Images News/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/DF/FC/A05B0252-BD73-4BC7-A09A-96F0A504FCDF/A05B0252-BD73-4BC7-A09A-96F0A504FCDF.jpg"></img></figure><figcaption>
|
||||
Spencer Platt/Getty Images News/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/DF/FC/A05B0252-BD73-4BC7-A09A-96F0A504FCDF/A05B0252-BD73-4BC7-A09A-96F0A504FCDF.jpg" alt="Online radio can take the place of a hired DJ." data-credit="Spencer Platt/Getty Images News/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Spencer Platt/Getty Images News/Getty Images </figcaption>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Avoid canned drinks, which guests often open, but don't finish. Serve pitchers of tap water with lemon and cucumber slices or sliced strawberries for an interesting and refreshing flavor. Opt for punches and non-alcoholic drinks for high school graduates that allow guests to dole out the exact amount they want to drink.</p></span> </p>
|
||||
<figure><img alt="Serve drinks in pitchers, not in cans." data-credit="evgenyb/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/EB/DB/8A04CCA7-3255-4225-B59A-C41441F8DBEB/8A04CCA7-3255-4225-B59A-C41441F8DBEB.jpg"></img></figure><figcaption>
|
||||
evgenyb/iStock/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/EB/DB/8A04CCA7-3255-4225-B59A-C41441F8DBEB/8A04CCA7-3255-4225-B59A-C41441F8DBEB.jpg" alt="Serve drinks in pitchers, not in cans." data-credit="evgenyb/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
evgenyb/iStock/Getty Images </figcaption>
|
||||
</div>
|
||||
|
||||
</span>
|
||||
|
@ -60,65 +70,79 @@
|
|||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Instead of inviting everyone you – and the graduate – know or ever knew, scale back the guest list. Forgo inviting guests that you or your grad haven't seen for eons. There is no reason to provide provisions for people who are essentially out of your lives. Sticking to a small, but personal, guest list allows more time to mingle with loved ones during the party, too.</p></span> </p>
|
||||
<figure><img alt="Limit guests to those close to the graduate." data-credit="Kane Skennar/Photodisc/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/94/10/08035476-0167-4A03-AADC-13A7E7AA1094/08035476-0167-4A03-AADC-13A7E7AA1094.jpg"></img></figure><figcaption>
|
||||
Kane Skennar/Photodisc/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/94/10/08035476-0167-4A03-AADC-13A7E7AA1094/08035476-0167-4A03-AADC-13A7E7AA1094.jpg" alt="Limit guests to those close to the graduate." data-credit="Kane Skennar/Photodisc/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Kane Skennar/Photodisc/Getty Images </figcaption>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>See if your grad and his best friend, girlfriend or close family member would consider hosting a joint party. You can split some of the expenses, especially when the two graduates share mutual friends. You'll also have another parent to bounce ideas off of and to help you stick to your budget when you're tempted to splurge.</p></span> </p>
|
||||
<figure><img alt="Throw a joint bash for big savings." data-credit="Mike Watson Images/Moodboard/Getty" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/06/49/4AD62696-FC95-4DA2-8351-42740C7B4906/4AD62696-FC95-4DA2-8351-42740C7B4906.jpg"></img></figure><figcaption>
|
||||
Mike Watson Images/Moodboard/Getty </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/06/49/4AD62696-FC95-4DA2-8351-42740C7B4906/4AD62696-FC95-4DA2-8351-42740C7B4906.jpg" alt="Throw a joint bash for big savings." data-credit="Mike Watson Images/Moodboard/Getty" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Mike Watson Images/Moodboard/Getty </figcaption>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Skip carving stations of prime rib and jumbo shrimp as appetizers, especially for high school graduation parties. Instead, serve some of the graduate's favorite side dishes that are cost effective, like a big pot of spaghetti with breadsticks. Opt for easy and simple food such as pizza, finger food and mini appetizers. </p>
|
||||
<p>Avoid pre-packaged foods and pre-made deli platters. These can be quite costly. Instead, make your own cheese and deli platters for less than half the cost of pre-made.</p></span> </p>
|
||||
<figure><img alt="Cost effective appetizers are just as satisfying as pre-made deli platters." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/D0/51/B6AED06C-5E19-4A26-9AAD-0E175F6251D0/B6AED06C-5E19-4A26-9AAD-0E175F6251D0.jpg"></img></figure><figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/D0/51/B6AED06C-5E19-4A26-9AAD-0E175F6251D0/B6AED06C-5E19-4A26-9AAD-0E175F6251D0.jpg" alt="Cost effective appetizers are just as satisfying as pre-made deli platters." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Instead of an evening dinner party, host a grad lunch or all appetizers party. Brunch and lunch fare or finger food costs less than dinner. Guests also tend to consume less alcohol in the middle of the day, which keeps cost down.</p></span> </p>
|
||||
<figure><img alt="A brunch gathering will cost less than a dinner party." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/35/B4/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435.jpg"></img></figure><figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/35/B4/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435/DD5FD05A-B631-4AFE-BC8F-FDACAD1EB435.jpg" alt="A brunch gathering will cost less than a dinner party." data-credit="Mark Stout/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
Mark Stout/iStock/Getty Images </figcaption>
|
||||
</div>
|
||||
<div id="relatedContentUpper" data-module="rcp_top">
|
||||
<header class>
|
||||
<h3>Other People Are Reading</h3>
|
||||
</header>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>
|
||||
<div>
|
||||
<div>
|
||||
<p><span><p>Decorate your party in the graduate's current school colors or the colors of the school he or she will be headed to next. Décor that is not specifically graduation-themed may cost a bit less, and any leftovers can be re-used for future parties, picnics and events.</p></span> </p>
|
||||
<figure><img alt="Theme the party by color without graduation-specific decor." data-credit="jethuynh/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true" src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/A1/FA/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1.jpg"></img></figure><figcaption>
|
||||
jethuynh/iStock/Getty Images </figcaption></div>
|
||||
<figure>
|
||||
<img src="http://img-aws.ehowcdn.com/640/cme/cme_public_images/www_ehow_com/cdn-write.demandstudios.com/upload/image/A1/FA/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1/2C368B34-8F6A-45F6-9DFC-0B0C4E33FAA1.jpg" alt="Theme the party by color without graduation-specific decor." data-credit="jethuynh/iStock/Getty Images" data-pin-ehow-hover="true" data-pin-no-hover="true">
|
||||
</figure>
|
||||
<figcaption>
|
||||
jethuynh/iStock/Getty Images </figcaption>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
|
||||
<h2>
|
||||
<a href="https://www.google.com/adsense/support/bin/request.py?contact=abg_afc&url=http://ehow.com/&hl=en&client=ehow&gl=US" target="_blank">Related Searches</a>
|
||||
<a target="_blank" href="https://www.google.com/adsense/support/bin/request.py?contact=abg_afc&url=http://ehow.com/&hl=en&client=ehow&gl=US">Related Searches</a>
|
||||
</h2>
|
||||
|
||||
|
||||
<p>Promoted By Zergnet</p>
|
||||
</article></div>
|
||||
|
||||
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
|
@ -1,19 +1,20 @@
|
|||
<article>
|
||||
<h2>Lorem</h2>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
|
||||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
<h2>Videos</h2>
|
||||
|
||||
<p>At root</p>
|
||||
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/LtOGa5M8AuU" width="560"></iframe>
|
||||
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" width="560"></iframe>
|
||||
<iframe allowfullscreen="" frameborder="0" height="281" mozallowfullscreen="" src="https://player.vimeo.com/video/32246206?color=ffffff+title=0+byline=0+portrait=0" webkitallowfullscreen="" width="500"></iframe>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen></iframe>
|
||||
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen></iframe>
|
||||
<iframe src="https://player.vimeo.com/video/32246206?color=ffffff+title=0+byline=0+portrait=0" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<p>In a paragraph</p>
|
||||
<p><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" width="560"></iframe></p>
|
||||
<p><iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen></iframe></p>
|
||||
<p>In a div</p>
|
||||
<p><iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/LtOGa5M8AuU" width="560"></iframe></p>
|
||||
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/LtOGa5M8AuU" frameborder="0" allowfullscreen></iframe></p>
|
||||
<h2>Foo</h2>
|
||||
<p>
|
||||
Tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[
|
||||
"https:\/\/o.aolcdn.com\/images\/dims?crop=1600%2C943%2C0%2C0&quality=85&format=jpg&resize=1600%2C943&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2Fd457f269d1400106a402302a310de800%2F205826071%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B1.jpg&client=a1acac3e1b3290917d92&signature=9fa7b29452763464190c6edff6822489df516d1b",
|
||||
"https:\/\/o.aolcdn.com\/images\/dims?thumbnail=45%2C45&quality=80&image_uri=http%3A%2F%2Fwww.blogcdn.com%2Fwww.engadget.com%2Fmedia%2F2016%2F03%2Fdevindra-engadget-headshot-small.jpg&client=cbc79c14efcebee57402&signature=e6ffba7468c380581b6589a70ce5d7c1ec40cd1d",
|
||||
"https:\/\/o.aolcdn.com\/images\/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F208%2F8%2FS7142088%2Fslug%2Fl%2Fxbox-one-x-review-gallery-1-1.jpg&client=cbc79c14efcebee57402&signature=9bb08b52e12de8e4060f863a52c613489529818d",
|
||||
"https:\/\/o.aolcdn.com\/images\/dims?crop=1600%2C1067%2C0%2C0&quality=85&format=jpg&resize=1600%2C1067&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F93beb86758ae1cf95721699e1e006e35%2F205826074%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=c0f2d36259c2c1decfb60aae364527cda2560d4a",
|
||||
"https:\/\/o.aolcdn.com\/images\/dims?crop=1600%2C949%2C0%2C0&quality=85&format=jpg&resize=1600%2C949&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F9ece7fdad1e7025dec06ac9bf98688d0%2F205826075%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B5.jpg&client=a1acac3e1b3290917d92&signature=9913883753141e7df322616bfe0bc41c6ecd80c8",
|
||||
|
|
|
@ -1,38 +1,3 @@
|
|||
<div role="main"><nav data-behavior="ContextNav" data-context-nav-offset="200">
|
||||
</nav><header>
|
||||
<p>
|
||||
|
||||
<h2> But only hardcore
|
||||
gamers will appreciate it. </h2>
|
||||
</p>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<div>
|
||||
<p><a href="http://fakehost/about/editors/devindra-hardawar/">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=45%2C45&quality=80&image_uri=http%3A%2F%2Fwww.blogcdn.com%2Fwww.engadget.com%2Fmedia%2F2016%2F03%2Fdevindra-engadget-headshot-small.jpg&client=cbc79c14efcebee57402&signature=e6ffba7468c380581b6589a70ce5d7c1ec40cd1d"></img></a></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</header><div data-behavior="BreakoutsHandler">
|
||||
<div>
|
||||
|
||||
<div>
|
||||
<article><div data-behavior="trigger_contents_nav" id="page_body">
|
||||
<div>
|
||||
|
||||
<div data-behavior="FitVids ">
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div data-behavior="Dropcap">
|
||||
<p>The <a href="https://www.engadget.com/2017/06/13/the-xbox-one-x-is-aspirational-in-the-purest-sense-of-the-word/">Xbox
|
||||
One X</a> is the ultimate video game system. It sports
|
||||
|
@ -49,35 +14,22 @@
|
|||
the $279 <a href="https://www.engadget.com/2016/08/02/xbox-one-s-review/">Xbox
|
||||
One S</a>. </p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<section><h4> Gallery: Xbox One
|
||||
</div><section>
|
||||
<h4> Gallery: Xbox One
|
||||
X | 14 Photos </h4>
|
||||
<div data-behavior="lightbox_trigger" data-eng-bang="{"gallery":803271,"slide":7142088,"index":0}" data-eng-mn="93511844" data-engadget-slideshow-id="803271"><p><a data-eng-bang="{"gallery":803271,"slide":7142088,"index":0}" data-engadget-slide-id="7142088" data-index="0" href="#">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F208%2F8%2FS7142088%2Fslug%2Fl%2Fxbox-one-x-review-gallery-1-1.jpg&client=cbc79c14efcebee57402&signature=9bb08b52e12de8e4060f863a52c613489529818d"></img></a></p>
|
||||
</div>
|
||||
</section></div>
|
||||
</div>
|
||||
<div data-behavior="lightbox_trigger" data-engadget-slideshow-id="803271" data-eng-bang="{"gallery":803271,"slide":7142088,"index":0}" data-eng-mn="93511844"><p><a href="#" data-index="0" data-engadget-slide-id="7142088" data-eng-bang="{"gallery":803271,"slide":7142088,"index":0}">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F208%2F8%2FS7142088%2Fslug%2Fl%2Fxbox-one-x-review-gallery-1-1.jpg&client=cbc79c14efcebee57402&signature=9bb08b52e12de8e4060f863a52c613489529818d">
|
||||
</a></p>
|
||||
|
||||
</div>
|
||||
</section><div>
|
||||
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
|
||||
<div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<ul><li>Most
|
||||
<ul>
|
||||
<li>Most
|
||||
powerful hardware ever in a home console
|
||||
</li>
|
||||
<li>Solid
|
||||
|
@ -86,10 +38,12 @@
|
|||
<li>4K Blu-ray
|
||||
drive is great for movie fans
|
||||
</li>
|
||||
</ul></div>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<ul><li>Expensive
|
||||
<ul>
|
||||
<li>Expensive
|
||||
</li>
|
||||
<li>Not worth
|
||||
it if you don’t have a 4K TV
|
||||
|
@ -97,7 +51,7 @@
|
|||
<li>Still no VR
|
||||
support
|
||||
</li>
|
||||
</ul></div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -108,17 +62,11 @@
|
|||
PlayStation 4 Pro. 4K/HDR enhanced games look great, but
|
||||
it’s lack of VR is disappointing in 2017.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</div><div xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<h3>Hardware</h3>
|
||||
<p><img alt="" data-credit="Devindra Hardawar/AOL" data-mep="2181678" src="https://o.aolcdn.com/images/dims?crop=1600%2C1067%2C0%2C0&quality=85&format=jpg&resize=1600%2C1067&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F93beb86758ae1cf95721699e1e006e35%2F205826074%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=c0f2d36259c2c1decfb60aae364527cda2560d4a"></img></p>
|
||||
<p><img data-credit="Devindra Hardawar/AOL" data-mep="2181678" src="https://o.aolcdn.com/images/dims?crop=1600%2C1067%2C0%2C0&quality=85&format=jpg&resize=1600%2C1067&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F93beb86758ae1cf95721699e1e006e35%2F205826074%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=c0f2d36259c2c1decfb60aae364527cda2560d4a" alt></p>
|
||||
<p>Despite all the power inside, the One X is
|
||||
Microsoft's smallest console to date. It looks
|
||||
similar to the Xbox One S, except it has an entirely
|
||||
|
@ -136,7 +84,7 @@
|
|||
That additional horsepower means the Xbox One X can
|
||||
run more games in full native 4K than the Sony's
|
||||
console.</p>
|
||||
<p><img alt="" data-credit="Devindra Hardawar/AOL" data-mep="2182489" src="https://o.aolcdn.com/images/dims?crop=1600%2C949%2C0%2C0&quality=85&format=jpg&resize=1600%2C949&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F9ece7fdad1e7025dec06ac9bf98688d0%2F205826075%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B5.jpg&client=a1acac3e1b3290917d92&signature=9913883753141e7df322616bfe0bc41c6ecd80c8"></img></p>
|
||||
<p><img data-credit="Devindra Hardawar/AOL" data-mep="2182489" src="https://o.aolcdn.com/images/dims?crop=1600%2C949%2C0%2C0&quality=85&format=jpg&resize=1600%2C949&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F9ece7fdad1e7025dec06ac9bf98688d0%2F205826075%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B5.jpg&client=a1acac3e1b3290917d92&signature=9913883753141e7df322616bfe0bc41c6ecd80c8" alt></p>
|
||||
<p>Along the front, there's the slot-loading 4K Blu-ray
|
||||
drive, a physical power button, a single USB port
|
||||
and a controller pairing button. And around back,
|
||||
|
@ -147,21 +95,12 @@
|
|||
Kinect around, you'll need to use a USB adapter to
|
||||
plug it in.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
|
||||
<div data-engadget-breakout-type="image">
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1599%252C1043%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1043%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F8b98ec8f6649158fe7448ac2f2695ac5%252F205826072%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B6.jpg%26client%3Da1acac3e1b3290917d92%26signature%3D353dad1308f98c2c9dfc82c58a540a8b2f1fe63c&client=cbc79c14efcebee57402&signature=60b7c061460d0d45f5d367b8a9c62978af6b76ce"></img><figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption></figure></div>
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1599%252C1043%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1043%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F8b98ec8f6649158fe7448ac2f2695ac5%252F205826072%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B6.jpg%26client%3Da1acac3e1b3290917d92%26signature%3D353dad1308f98c2c9dfc82c58a540a8b2f1fe63c&client=cbc79c14efcebee57402&signature=60b7c061460d0d45f5d367b8a9c62978af6b76ce">
|
||||
<figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p>The console's controller hasn't changed since its
|
||||
last mini-upgrade with the Xbox One S. That revision
|
||||
|
@ -176,21 +115,12 @@
|
|||
has rechargeable controllers.</p>
|
||||
<h3>In use</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
|
||||
<div data-engadget-breakout-type="image">
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C900%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C900%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F1885534bd201fc37481b806645c1fc8b%252F205828119%252FXbox%252Bone%252BX%252Bscreenshot%252Bgallery%252B8.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Df63cf67c88b37fd9424855984e45f6b950c8c11a&client=cbc79c14efcebee57402&signature=0adca80fc8ee26a7353be639082881450a5ad49f"></img><figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption></figure></div>
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C900%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C900%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252F1885534bd201fc37481b806645c1fc8b%252F205828119%252FXbox%252Bone%252BX%252Bscreenshot%252Bgallery%252B8.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Df63cf67c88b37fd9424855984e45f6b950c8c11a&client=cbc79c14efcebee57402&signature=0adca80fc8ee26a7353be639082881450a5ad49f">
|
||||
<figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p>You won't find any major differences between the One
|
||||
X and the last Xbox at first — aside from a more
|
||||
|
@ -223,35 +153,12 @@
|
|||
times were on-par with what I've seen with the game
|
||||
on the Xbox One S.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div data-engadget-breakout-type="e2ehero">
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F8352a8a14e88e2ca2ba5be4d8381a055%2F205828115%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B1.jpg&client=a1acac3e1b3290917d92&signature=d2ccb22e0eaabeb05bfe46e83dbe26fd07f01da8"></img><div>
|
||||
<div>
|
||||
<div>
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F8352a8a14e88e2ca2ba5be4d8381a055%2F205828115%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B1.jpg&client=a1acac3e1b3290917d92&signature=d2ccb22e0eaabeb05bfe46e83dbe26fd07f01da8">
|
||||
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</figure></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p>You can also play in Performance mode, which bumps
|
||||
the frame rate up to 60FPS and uses higher quality
|
||||
|
@ -278,24 +185,16 @@
|
|||
levels of bloom lighting and shadow detail.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div data-engadget-breakout-type="gallery">
|
||||
<section><h3> Gallery: Xbox
|
||||
<section data-engadget-breakout-type="gallery">
|
||||
<h3> Gallery: Xbox
|
||||
One X screenshots | 9 Photos </h3>
|
||||
<div data-behavior="lightbox_trigger" data-eng-bang="{"gallery":803330,"slide":7142924}" data-eng-mn="93511844" data-engadget-slideshow-id="803330"><p><a data-eng-bang="{"gallery":803330,"slide":7142924}" data-engadget-slide-id="7142924" data-index="0" href="#">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F292%2F4%2FS7142924%2Fslug%2Fl%2Fxbox-one-x-screenshot-gallery-2-1.jpg&client=cbc79c14efcebee57402&signature=38c95635c7aad58a8a48038e05589f5cf35b1e28"></img></a></p>
|
||||
<div data-behavior="lightbox_trigger" data-engadget-slideshow-id="803330" data-eng-bang="{"gallery":803330,"slide":7142924}" data-eng-mn="93511844"><p><a href="#" data-index="0" data-engadget-slide-id="7142924" data-eng-bang="{"gallery":803330,"slide":7142924}">
|
||||
<img src="https://o.aolcdn.com/images/dims?thumbnail=980%2C653&quality=80&image_uri=https%3A%2F%2Fs.blogcdn.com%2Fslideshows%2Fimages%2Fslides%2F714%2F292%2F4%2FS7142924%2Fslug%2Fl%2Fxbox-one-x-screenshot-gallery-2-1.jpg&client=cbc79c14efcebee57402&signature=38c95635c7aad58a8a48038e05589f5cf35b1e28">
|
||||
</a></p>
|
||||
|
||||
</div>
|
||||
</section></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
</section>
|
||||
<div>
|
||||
<p><em>Killer Instinct</em> and <em>Super Lucky's
|
||||
Tale</em> run in 4K at a smooth 60FPS. They both
|
||||
|
@ -329,35 +228,12 @@
|
|||
Basically, don't expect your entire 360 library to
|
||||
get enhanced.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div data-engadget-breakout-type="e2ehero">
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2Facb08903fbe26ad77b80db8c8e7e8fb1%2F205828118%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=21630fa5ec6d8fdce2c35f7e1f652636a2d8efe7"></img><div>
|
||||
<div>
|
||||
<div>
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?crop=1600%2C900%2C0%2C0&quality=85&format=jpg&resize=1600%2C900&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2Facb08903fbe26ad77b80db8c8e7e8fb1%2F205828118%2FXbox%2Bone%2BX%2Bscreenshot%2Bgallery%2B7.jpg&client=a1acac3e1b3290917d92&signature=21630fa5ec6d8fdce2c35f7e1f652636a2d8efe7">
|
||||
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</figure></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p>Even if a game isn't specifically tuned for the new
|
||||
console, Microsoft says you might still see some
|
||||
|
@ -376,7 +252,7 @@
|
|||
more widely supported, but it would have been nice
|
||||
to see Dolby's, too.</p>
|
||||
<p>
|
||||
<iframe allowfullscreen="" frameborder="0" gesture="media" height="360" src="https://www.youtube.com/embed/c8aFcHFu8QM" width="640"></iframe>
|
||||
<iframe allowfullscreen frameborder="0" gesture="media" height="360" src="https://www.youtube.com/embed/c8aFcHFu8QM" width="640"></iframe>
|
||||
</p>
|
||||
<p>And speaking of Dolby technology, Microsoft is also
|
||||
highlighting Atmos support on the One X, just like
|
||||
|
@ -402,21 +278,12 @@
|
|||
PlayStation VR.</p>
|
||||
<h3>Pricing and the competition</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
|
||||
|
||||
<div data-engadget-breakout-type="image">
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C1027%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1027%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252Fa2c8ba1caccdbb9e0559797e5141eafd%252F205826078%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B11.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Da11bcddced805c6e3698f8ce0494102aef057265&client=cbc79c14efcebee57402&signature=1e9bd192add2772bc842a34e67b7572cfd1b265a"></img><figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption></figure></div>
|
||||
<figure><img src="https://o.aolcdn.com/images/dims?resize=980%2C640&quality=100&image_uri=https%3A%2F%2Fo.aolcdn.com%2Fimages%2Fdims%3Fcrop%3D1600%252C1027%252C0%252C0%26quality%3D85%26format%3Djpg%26resize%3D1600%252C1027%26image_uri%3Dhttp%253A%252F%252Fo.aolcdn.com%252Fhss%252Fstorage%252Fmidas%252Fa2c8ba1caccdbb9e0559797e5141eafd%252F205826078%252FXbox%252BOne%252BX%252Breview%252Bgallery%252B11.jpg%26client%3Da1acac3e1b3290917d92%26signature%3Da11bcddced805c6e3698f8ce0494102aef057265&client=cbc79c14efcebee57402&signature=1e9bd192add2772bc842a34e67b7572cfd1b265a">
|
||||
<figcaption><span>Devindra Hardawar/AOL</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p>The biggest knock against the Xbox One X is its $500
|
||||
price. The PS4 Pro launched at $400 last year, and
|
||||
|
@ -449,7 +316,7 @@
|
|||
PC, you won't be missing out on much by ditching
|
||||
consoles.</p>
|
||||
<h3>Wrap-up</h3>
|
||||
<p><img alt="" data-credit="Devindra Hardawar/AOL" data-mep="2181681" src="https://o.aolcdn.com/images/dims?crop=1600%2C1028%2C0%2C0&quality=85&format=jpg&resize=1600%2C1028&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F5396460ef8b6bde7fb7272d9e66a7701%2F205826076%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B9.jpg&client=a1acac3e1b3290917d92&signature=f5b5b4b986c2f8b5031a4469ae0ecec82aff65b0"></img></p>
|
||||
<p><img data-credit="Devindra Hardawar/AOL" data-mep="2181681" src="https://o.aolcdn.com/images/dims?crop=1600%2C1028%2C0%2C0&quality=85&format=jpg&resize=1600%2C1028&image_uri=http%3A%2F%2Fo.aolcdn.com%2Fhss%2Fstorage%2Fmidas%2F5396460ef8b6bde7fb7272d9e66a7701%2F205826076%2FXbox%2BOne%2BX%2Breview%2Bgallery%2B9.jpg&client=a1acac3e1b3290917d92&signature=f5b5b4b986c2f8b5031a4469ae0ecec82aff65b0" alt></p>
|
||||
<p>Ultimately, the Xbox One X offers some major
|
||||
performance upgrades that gamers will notice --
|
||||
especially if you're coming from an original Xbox
|
||||
|
@ -459,21 +326,6 @@
|
|||
that will matter. It's exactly what the company
|
||||
promised: the fastest game console ever made.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<h2> From around the web </h2>
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Author": "Written by Edward Wallace",
|
||||
"Author": null,
|
||||
"Direction": null,
|
||||
"Excerpt": "Just when you think the marketing behind the film couldn't get any more amazing, they go and release a music video from the Deadpool 2 soundtrack starring Canadian singer Céline Dion.",
|
||||
"Image": "http:\/\/www.fortressofsolitude.co.za\/wp-content\/uploads\/2018\/05\/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack.jpg",
|
||||
|
|
|
@ -1 +1 @@
|
|||
<div id="primary"><div id="content" role="main"> <article id="post-116764"><p><span> <a href="http://www.fortressofsolitude.co.za/celine-dion-deadpool-2-soundtrack-ashes/" title="Céline Dion Belches Her Way Onto Deadpool 2's Soundtrack"><img alt="Céline Dion Belches Her Way Onto Deadpool 2's Soundtrack" height="400" sizes="(max-width: 750px) 100vw, 750px" src="http://www.fortressofsolitude.co.za/wp-content/uploads/2018/05/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack-750x400.jpg" srcset="http://www.fortressofsolitude.co.za/wp-content/uploads/2018/05/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack-750x400.jpg 750w, http://www.fortressofsolitude.co.za/wp-content/uploads/2018/05/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack-24x14.jpg 24w" width="750"></img></a> </span></p><header></header><div><hr></hr><div><div><p><span>R</span>yan Reynolds never stops surprising fans with his <a href="http://www.fortressofsolitude.co.za/new-deadpool-2-trailer/">Deadpool</a>, a.k.a. the Merc with the Mouth, persona. Just when you think the marketing behind the film couldn’t get any more amazing, they go and release a music video from the <strong><em>Deadpool 2</em></strong> soundtrack starring Canadian singer Céline Dion. Yes, the one who sang the <em>Titanic</em> theme song. Your eyes do not deceive you.</p><center><blockquote data-lang="en"><p dir="ltr" lang="tl">Showtime, Mama. <a href="https://twitter.com/hashtag/EffortMaximal?src=hash&ref_src=twsrc%5Etfw" rel="nofollow" target="_blank">#EffortMaximal</a> <a href="https://twitter.com/hashtag/Deadpool2?src=hash&ref_src=twsrc%5Etfw" rel="nofollow" target="_blank">#Deadpool2</a> <a href="https://t.co/ZKLrucXJO4" rel="nofollow" target="_blank">pic.twitter.com/ZKLrucXJO4</a></p><p>— Ryan Reynolds (@VancityReynolds) <a href="https://twitter.com/VancityReynolds/status/992018849225695242?ref_src=twsrc%5Etfw" rel="nofollow" target="_blank">May 3, 2018</a></p></blockquote></center><p>“What’s left to say? These prayers ain’t working anymore. Every word shot down in flames. What’s left to do with these broken pieces on the floor? I’m losing my voice calling on you,” Dion croons in the video for “Ashes”. Near the end of it, the filthy, foul-mouthed <a href="http://www.fortressofsolitude.co.za/hilarious-deadpool-2-teaser-bob-ross/">Deadpool</a> shows up in a surprising twist mentioning that he should have gotten N’sync instead.</p><h3><strong><em>Deadpool 2</em></strong> opens in theatres on May 18.</h3></div></div></div><hr></hr></article></div></div>
|
||||
<div id="primary" role="main"> <article id="post-116764"><p><span> <a href="http://www.fortressofsolitude.co.za/celine-dion-deadpool-2-soundtrack-ashes/" title="Céline Dion Belches Her Way Onto Deadpool 2's Soundtrack"><img width="750" height="400" src="http://www.fortressofsolitude.co.za/wp-content/uploads/2018/05/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack-750x400.jpg" alt="Céline Dion Belches Her Way Onto Deadpool 2's Soundtrack" srcset="http://www.fortressofsolitude.co.za/wp-content/uploads/2018/05/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack-750x400.jpg 750w, http://www.fortressofsolitude.co.za/wp-content/uploads/2018/05/Céline-Dion-Belches-Her-Way-Onto-Deadpool-2s-Soundtrack-24x14.jpg 24w" sizes="(max-width: 750px) 100vw, 750px"></a> </span></p><div><hr><div><p><span>R</span>yan Reynolds never stops surprising fans with his <a href="http://www.fortressofsolitude.co.za/new-deadpool-2-trailer/">Deadpool</a>, a.k.a. the Merc with the Mouth, persona. Just when you think the marketing behind the film couldn’t get any more amazing, they go and release a music video from the <strong><em>Deadpool 2</em></strong> soundtrack starring Canadian singer Céline Dion. Yes, the one who sang the <em>Titanic</em> theme song. Your eyes do not deceive you.</p><center><blockquote data-lang="en"><p lang="tl" dir="ltr">Showtime, Mama. <a rel="nofollow" target="_blank" href="https://twitter.com/hashtag/EffortMaximal?src=hash&ref_src=twsrc%5Etfw">#EffortMaximal</a> <a rel="nofollow" target="_blank" href="https://twitter.com/hashtag/Deadpool2?src=hash&ref_src=twsrc%5Etfw">#Deadpool2</a> <a rel="nofollow" target="_blank" href="https://t.co/ZKLrucXJO4">pic.twitter.com/ZKLrucXJO4</a></p><p>— Ryan Reynolds (@VancityReynolds) <a rel="nofollow" target="_blank" href="https://twitter.com/VancityReynolds/status/992018849225695242?ref_src=twsrc%5Etfw">May 3, 2018</a></p></blockquote></center><p>“What’s left to say? These prayers ain’t working anymore. Every word shot down in flames. What’s left to do with these broken pieces on the floor? I’m losing my voice calling on you,” Dion croons in the video for “Ashes”. Near the end of it, the filthy, foul-mouthed <a href="http://www.fortressofsolitude.co.za/hilarious-deadpool-2-teaser-bob-ross/">Deadpool</a> shows up in a surprising twist mentioning that he should have gotten N’sync instead.</p><h3><strong><em>Deadpool 2</em></strong> opens in theatres on May 18.</h3></div></div><hr></article></div>
|
|
@ -6,7 +6,7 @@
|
|||
<p> 翱翔于距地球数千公里的太空中,进入广袤漆黑的未知领域,是一项艰苦卓绝的工作。这让人感到巨大压力和极度恐慌。那么,为什么不能让宇航员来一杯“地球末日”鸡尾酒来放松一下?</p>
|
||||
<p> 不幸的是,对于希望能喝上一杯的太空探险者,那些将他们送上太空的政府机构普遍禁止他们染指包括酒在内的含酒精饮料。</p>
|
||||
<p> 但是,很快普通人都会有机会向人类“最终的边疆”出发——以平民化旅行的形式,去探索和殖民火星。确实,火星之旅将是一次令人感到痛苦的旅行,可能一去不复返并要几年时间才能完成,但是否应该允许参与者在旅程中痛饮一番?或至少携带能在火星上发酵自制酒精饮料的设备?</p>
|
||||
<p><img alt="(Credit: Nasa)" id="45395168" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e5929.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></img></p>
|
||||
<p><img id="45395168" alt="(Credit: Nasa)" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e5929.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></p>
|
||||
<p>
|
||||
<span face="楷体"> 图注:巴兹?奥尔德林(Buzz Aldrin)可能是第二个在月球上行走的人,但他是第一个在月球上喝酒的人</span>
|
||||
</p>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<p> 所以,如果酒精对人体的物理效应与海拔高度无关,那么在国际空间站上睡前小饮一杯不应该是一个大问题,对吧?错了。</p>
|
||||
<p> 美国宇航局约翰逊航天中心发言人丹尼尔·霍特(Daniel Huot)表示:“国际空间站上的宇航员不允许喝酒。在国际空间站上,酒精和其它挥发性化合物的使用受到控制,因为它们的挥发物可能对该站的水回收系统产生影响。”</p>
|
||||
<p> 为此,国际空间站上的宇航员甚至没有被提供含有酒精的产品,例如漱口水、香水或须后水。如果在国际空间站上饮酒狂欢,溢出的啤酒也可能存在损坏设备的风险。</p>
|
||||
<p><img alt="(Credit: iStock)" id="45395150" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e592a.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></img></p>
|
||||
<p><img id="45395150" alt="(Credit: iStock)" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e592a.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></p>
|
||||
<p>
|
||||
<span face="楷体"> 图注:测试表明,有关人在高空中喝酒更容易醉的传言是不正确的</span>
|
||||
</p>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<p> 因此,即使宇航员自己被禁止在地球轨道上饮酒,但他们正在做的工作可以提高在地上消费的酒的质量。</p>
|
||||
<p> 相比之下,执行登陆火星任务的人将远离家乡几年,而不是几个月,因此可能会有人提出有关禁止饮酒的规定可以放松一些。</p>
|
||||
<p> 然而,像戴夫?汉森这样的专家认为,继续禁止饮酒并没有什么害处。除了实际的安全问题,饮酒还可能有其它挑战。汉森认为,地球人存在许多社会文化方面的差异,而且人连续几年时间呆在一个狭小的空间里,很容易突然发怒,这些因素都使饮酒问题变得很棘手。</p>
|
||||
<p><img alt="(Credit: David Frohman/Peachstate Historical Consulting Inc)" id="45395153" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e592d.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"></img></p>
|
||||
<p><img id="45395153" alt="(Credit: David Frohman/Peachstate Historical Consulting Inc)" src="http://imgtech.gmw.cn/attachement/jpg/site2/20170310/448a5bc1e2861a2c4e592d.jpg" title="宇航员在太空中喝酒会怎么样?后果很严重"> </p>
|
||||
<p>
|
||||
<span face="楷体"> 图注:奥尔德林的圣餐杯回到了地球上</span>
|
||||
</p>
|
||||
|
@ -49,7 +49,7 @@
|
|||
<p> 原标题:他晚于阿姆斯特朗登月 却是首个敢在月球喝酒的人</p>
|
||||
<p><strong> 出品︱网易科学人栏目组 胖胖</strong></p>
|
||||
<p><strong> 作者︱春春</strong>
|
||||
<a href="http://www.gmw.cn" target="_blank"><img src="https://img.gmw.cn/pic/content_logo.png" title="返回光明网首页"></img></a>
|
||||
<a href="http://www.gmw.cn" target="_blank"><img src="https://img.gmw.cn/pic/content_logo.png" title="返回光明网首页"></a>
|
||||
</p>
|
||||
|
||||
<p>[责任编辑:肖春芳]</p>
|
||||
|
|
|
@ -1,20 +1,34 @@
|
|||
<div>
|
||||
|
||||
|
||||
<figure><img src="http://3.f.ix.de/scale/geometry/600/q75/imgs/18/1/4/6/2/3/5/1/Barcode-Scanner-With-Border-fc08c913da5cea5d.jpeg"></img><figcaption><p>1Password scannt auch QR-Codes.</p>
|
||||
<figure>
|
||||
<img src="http://3.f.ix.de/scale/geometry/600/q75/imgs/18/1/4/6/2/3/5/1/Barcode-Scanner-With-Border-fc08c913da5cea5d.jpeg">
|
||||
|
||||
<figcaption>
|
||||
|
||||
<p>1Password scannt auch QR-Codes.</p>
|
||||
|
||||
|
||||
<p>(Bild: Hersteller)</p>
|
||||
|
||||
</figcaption></figure><p><strong>Das in der iOS-Version bereits enthaltene TOTP-Feature ist nun auch für OS X 10.10 verfügbar. Zudem gibt es neue Zusatzfelder in der Datenbank und weitere Verbesserungen.</strong></p>
|
||||
<p><a href="https://itunes.apple.com/de/app/1password-password-manager/id443987910" rel="external" target="_blank">AgileBits hat Version 5.3 seines bekannten Passwortmanagers 1Password für OS X freigegeben.</a> Mit dem Update wird eine praktische Funktion nachgereicht, die <a href="http://fakehost/mac-and-i/meldung/Passwortmanager-1Password-mit-groesseren-Updates-fuer-OS-X-und-iOS-2529204.html">die iOS-Version der Anwendung bereits seit längerem beherrscht</a>: Das direkte Erstellen von Einmal-Passwörtern. Unterstützt wird dabei der <a href="https://blog.agilebits.com/2015/01/26/totp-for-1password-users/" rel="external" target="_blank">TOTP-Standard</a> (Time-Based One-Time Passwords), den unter anderem Firmen wie Evernote, Dropbox oder Google einsetzen, um ihre Zugänge besser abzusichern. Neben Account und regulärem Passwort wird dabei dann ein Zusatzcode verlangt, der nur kurze Zeit gilt.</p>
|
||||
<p>Zur TOTP-Nutzung muss zunächst ein Startwert an 1Password übergeben werden. Das geht unter anderem per QR-Code, den die App über ein neues Scanfenster selbst einlesen kann – etwa aus dem Webbrowser. Eine Einführung in die Technik gibt <a href="http://1pw.ca/TOTPvideoMac" rel="external" target="_blank">ein kurzes Video</a>. Die TOTP-Unterstützung in 1Password erlaubt es, auf ein zusätzliches Gerät (z.B. ein iPhone) neben dem Mac zu verzichten, das den Code liefert – was allerdings auch die Sicherheit verringert, weil es keinen "echten" zweiten Faktor mehr gibt.</p>
|
||||
</figcaption>
|
||||
|
||||
</figure>
|
||||
|
||||
|
||||
|
||||
<p><strong>Das in der iOS-Version bereits enthaltene TOTP-Feature ist nun auch für OS X 10.10 verfügbar. Zudem gibt es neue Zusatzfelder in der Datenbank und weitere Verbesserungen.</strong></p>
|
||||
<p><a rel="external" target="_blank" href="https://itunes.apple.com/de/app/1password-password-manager/id443987910">AgileBits hat Version 5.3 seines bekannten Passwortmanagers 1Password für OS X freigegeben.</a> Mit dem Update wird eine praktische Funktion nachgereicht, die <a href="http://fakehost/mac-and-i/meldung/Passwortmanager-1Password-mit-groesseren-Updates-fuer-OS-X-und-iOS-2529204.html">die iOS-Version der Anwendung bereits seit längerem beherrscht</a>: Das direkte Erstellen von Einmal-Passwörtern. Unterstützt wird dabei der <a rel="external" target="_blank" href="https://blog.agilebits.com/2015/01/26/totp-for-1password-users/">TOTP-Standard</a> (Time-Based One-Time Passwords), den unter anderem Firmen wie Evernote, Dropbox oder Google einsetzen, um ihre Zugänge besser abzusichern. Neben Account und regulärem Passwort wird dabei dann ein Zusatzcode verlangt, der nur kurze Zeit gilt.</p>
|
||||
<p>Zur TOTP-Nutzung muss zunächst ein Startwert an 1Password übergeben werden. Das geht unter anderem per QR-Code, den die App über ein neues Scanfenster selbst einlesen kann – etwa aus dem Webbrowser. Eine Einführung in die Technik gibt <a rel="external" target="_blank" href="http://1pw.ca/TOTPvideoMac">ein kurzes Video</a>. Die TOTP-Unterstützung in 1Password erlaubt es, auf ein zusätzliches Gerät (z.B. ein iPhone) neben dem Mac zu verzichten, das den Code liefert – was allerdings auch die Sicherheit verringert, weil es keinen "echten" zweiten Faktor mehr gibt.</p>
|
||||
<p>Update 5.3 des Passwortmanagers liefert auch noch weitere Verbesserungen. So gibt es die Möglichkeit, FaceTime-Audio- oder Skype-Anrufe aus 1Password zu starten, die Zahl der Zusatzfelder in der Datenbank wurde erweitert und der Umgang mit unterschiedlichen Zeitzonen klappt besser. Die Engine zur Passworteingabe im Browser soll beschleunigt worden sein.</p>
|
||||
<p>1Password kostet aktuell knapp 50 Euro im Mac App Store und setzt in seiner aktuellen Version mindestens OS X 10.10 voraus.
|
||||
|
||||
|
||||
|
||||
<span>(<a href="mailto:bsc@heise.de" title="Ben Schwan">bsc</a>)</span>
|
||||
<br></br></p>
|
||||
<span>(<a title="Ben Schwan" href="mailto:bsc@heise.de">bsc</a>)</span>
|
||||
<br>
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
|
@ -1,14 +1,13 @@
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<p><img alt="A new Bill would require telecommunications service providers to store so-called ‘metadat" data-src="http://api.news.com.au/content/1.0/heraldsun/images/1227261885862?format=jpg&group=iphone&size=medium" src="http://api.news.com.au/content/1.0/heraldsun/images/1227261885862?format=jpg&group=iphone&size=medium"></img></p>
|
||||
<p><img data-src="http://api.news.com.au/content/1.0/heraldsun/images/1227261885862?format=jpg&group=iphone&size=medium" alt="A new Bill would require telecommunications service providers to store so-called ‘metadat">
|
||||
</p>
|
||||
<p>
|
||||
<span id="imgCaption">A new Bill would require telecommunications service providers to store so-called ‘metadata’ for two years.</span>
|
||||
<span><em>Source:</em>
|
||||
Supplied</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>
|
||||
A HIGH-powered federal government team has been doing the rounds of media organisations in the past few days in an attempt to allay concerns about the impact of new surveillance legislation on press freedom. It failed.
|
||||
</strong></p>
|
||||
|
@ -17,10 +16,6 @@
|
|||
|
||||
|
||||
<div id="read-more">
|
||||
|
||||
|
||||
<div id="read-more-content">
|
||||
<p>The Bill would require telecommunications service providers to store so-called “metadata” — the who, where, when and how of a communication, but not its content — for two years so security and law enforcement agencies can access it without warrant. Few would argue against the use of such material to catch criminals or terrorists. But, as Parliament’s Joint Committee on Intelligence and Security has pointed out, it would also be used “for the purpose of determining the identity of a journalist’s sources”.</p><p>And that should ring warning bells for anyone genuinely concerned with the health of our democracy. Without the ability to protect the identity of sources, journalists would be greatly handicapped in exposing corruption, dishonesty, waste, incompetence and misbehaviour by public officials.</p><p>The Press Council is concerned the laws would crush investigative journalism.</p><p>“These legitimate concerns cannot be addressed effectively short of exempting journalists and media organisations,” says president David Weisbrot.</p><p>The media union is adamant journalists’ metadata must be exempted from the law. That’s what media bosses want, too, though they have a fallback position based on new safeguards being implemented in Britain.</p><p>That would prevent access to the metadata of journalists or media organisations without a judicial warrant. There would be a code including — according to the explanatory notes of the British Bill — “provision to protect the public interest in the confidentiality of journalistic sources”.</p><p>In their meetings this week, the government team boasted of concessions in the new Data Retention Bill. The number of agencies able to access metadata will be reduced by excluding such organisations as the RSPCA and local councils. And whenever an authorisation is issued for access to information about a journalist’s sources, the Ombudsman (or, where ASIO is involved, the Inspector-General of Intelligence and Security) will receive a copy.</p><p>That does nothing to solve the problem. The Government has effectively admitted as much by agreeing that the parliamentary committee should conduct a separate review of how to deal with the issue of journalists’ sources.</p><p>But another inquiry would be a waste of time — the committee has already received and considered dozens of submissions on the subject. The bottom line is that the Government does not deny that the legislation is flawed, but is demanding it be passed anyway with the possibility left open of a repair job down the track. That is a ridiculous approach.</p><p>Claims that immediate action is imperative do not stand up. These are measures that won’t come into full effect for two years. Anyway, amending the Bill to either exempt journalists or adopt the UK model could be done quickly, without any risk to national security.</p><p>AS Opposition Leader Bill Shorten said in a letter to Abbott last month: “Press freedom concerns about mandatory data retention would ideally be addressed in this Bill to avoid the need for future additional amendments or procedures to be put in place in the future.”</p><p>The Data Retention Bill will be debated in the House of Representatives this week. Then, on Friday, CEOs from leading media organisations will front the parliamentary committee to air their concerns before the legislation goes to the Senate.</p><p>Those CEOs should make it clear they are just as angry about this as they were about Stephen Conroy’s attempt to impinge on press freedom through media regulation under the previous Labor government.</p><p>Memories of the grief Conroy brought down on his head would undoubtedly make Abbott sit up and take notice.</p><p><b>LAURIE OAKES IS THE NINE NETWORK POLITICAL EDITOR </b></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,7 +1,10 @@
|
|||
[
|
||||
"http:\/\/fakehost\/test\/..\/..\/..\/gazou\/pc_gazou\/aesop\/aesop052.jpg",
|
||||
"http:\/\/fakehost\/test\/..\/..\/..\/..\/366\/logo_bana\/corner_1.gif",
|
||||
"http:\/\/fakehost\/test\/..\/..\/..\/..\/366\/logo_bana\/corner_2.gif",
|
||||
"http:\/\/fakehost\/test\/..\/..\/..\/gazou\/origami_gazou\/kantan\/dogface.gif",
|
||||
"http:\/\/fakehost\/test\/..\/..\/..\/gazou\/origami_gazou\/kantan\/dog.gif"
|
||||
"http:\/\/fakehost\/366\/logo_bana\/corner_1.gif",
|
||||
"http:\/\/fakehost\/366\/logo_bana\/corner_2.gif",
|
||||
"http:\/\/fakehost\/gazou\/pc_gazou\/aesop\/aesop052.jpg",
|
||||
"http:\/\/fakehost\/gazou\/origami_gazou\/kantan\/dogface.gif",
|
||||
"http:\/\/fakehost\/gazou\/origami_gazou\/kantan\/dog.gif",
|
||||
"http:\/\/fakehost\/gazou\/pc_gazou\/all\/top_bana\/back_logo_r.gif",
|
||||
"file:\/\/\/C|\/Documents%20and%20Settings\/%E7%A6%8F%E5%A8%98note\/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97\/company_website15\/image\/spacer.gif",
|
||||
"file:\/\/\/C|\/Documents%20and%20Settings\/%E7%A6%8F%E5%A8%98note\/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97"
|
||||
]
|
|
@ -1,13 +1,48 @@
|
|||
<div width="619">
|
||||
<div>
|
||||
<td>
|
||||
<table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7">
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
<a href="http://fakehost/test/../../../index.html">福娘童話集</a> > <a href="http://fakehost/test/../index.html">きょうのイソップ童話</a> > <a href="http://fakehost/test/../itiran/01gatu.htm">1月のイソップ童話</a> > 欲張りなイヌ
|
||||
<a href="http://fakehost/index.html">福娘童話集</a> > <a href="http://fakehost/index.html">きょうのイソップ童話</a> > <a href="http://fakehost/itiran/01gatu.htm">1月のイソップ童話</a> > 欲張りなイヌ
|
||||
</p>
|
||||
<div>
|
||||
<p><span color="#FF0000" size="+2">元旦のイソップ童話</span></p><p><img alt="よくばりなイヌ" height="360" src="http://fakehost/test/../../../gazou/pc_gazou/aesop/aesop052.jpg" width="480"></img></p><p>
|
||||
<p><span color="#FF0000" size="+2">元旦のイソップ童話</span></p><p><img src="http://fakehost/gazou/pc_gazou/aesop/aesop052.jpg" alt="よくばりなイヌ" width="480" height="360"></p><p>
|
||||
欲張りなイヌ</p><p><a href="http://hukumusume.com/douwa/English/aesop/01/01_j.html">ひらがな</a> ←→ <a href="http://hukumusume.com/douwa/English/aesop/01/01_j&E.html">日本語・英語</a> ←→ <a href="http://hukumusume.com/douwa/English/aesop/01/01_E.html">English</a></p></div>
|
||||
<div>
|
||||
<table readabilityDataTable="0"><tbody><tr><td>
|
||||
<img height="7" src="http://fakehost/test/../../../../366/logo_bana/corner_1.gif" width="7"></img></td>
|
||||
<table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7">
|
||||
</td>
|
||||
<td>
|
||||
<span color="#FF0000"><b>おりがみをつくろう</b></span>
|
||||
</td>
|
||||
|
@ -15,25 +50,178 @@
|
|||
<span size="-1">( <a href="http://www.origami-club.com/index.html">おりがみくらぶ</a> より)</span>
|
||||
</td>
|
||||
<td>
|
||||
<img height="7" src="http://fakehost/test/../../../../366/logo_bana/corner_2.gif" width="7"></img></td>
|
||||
</tr><tr><td colspan="4">
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<p>
|
||||
<a href="http://www.origami-club.com/easy/dogfase/index.html"><span size="+2"><img alt="犬の顔の折り紙" height="51" src="http://fakehost/test/../../../gazou/origami_gazou/kantan/dogface.gif" width="73"></img>いぬのかお</span></a> <a href="http://www.origami-club.com/easy/dog/index.html"><img alt="犬の顔の紙" height="43" src="http://fakehost/test/../../../gazou/origami_gazou/kantan/dog.gif" width="62"></img><span size="+2">いぬ</span></a>
|
||||
</p></td>
|
||||
</tr></tbody></table></div><table readabilityDataTable="0"><tbody><tr><td>
|
||||
<a href="http://www.origami-club.com/easy/dogfase/index.html"><span size="+2"><img src="http://fakehost/gazou/origami_gazou/kantan/dogface.gif" alt="犬の顔の折り紙" width="73" height="51">いぬのかお</span></a> <a href="http://www.origami-club.com/easy/dog/index.html"><img src="http://fakehost/gazou/origami_gazou/kantan/dog.gif" alt="犬の顔の紙" width="62" height="43"><span size="+2">いぬ</span></a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
♪音声配信(html5)
|
||||
</td>
|
||||
</tr><tr><td>
|
||||
<audio controls="" src="http://ohanashi2.up.seesaa.net/mp3/ae_0101.mp3"></audio></td>
|
||||
</tr><tr><td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<audio src="http://ohanashi2.up.seesaa.net/mp3/ae_0101.mp3" controls></audio>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="http://www.voiceblog.jp/onokuboaki/"><span size="-1">亜姫の朗読☆ イソップ童話より</span></a>
|
||||
</td>
|
||||
</tr></tbody></table><p>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
肉をくわえたイヌが、橋を渡っていました。 ふと下を見ると、川の中にも肉をくわえたイヌがいます。 イヌはそれを見て、思いました。(あいつの肉の方が、大きそうだ) イヌは、くやしくてたまりません。 (そうだ、あいつをおどかして、あの肉を取ってやろう) そこでイヌは、川の中のイヌに向かって思いっきり吠えました。 「ウゥー、ワン!!」 そのとたん、くわえていた肉はポチャンと川の中に落ちてしまいました。 「ああー、ぁぁー」 川の中には、がっかりしたイヌの顔がうつっています。 さっきの川の中のイヌは、水にうつった自分の顔だったのです。 同じ物を持っていても、人が持っている物の方が良く見え、また、欲張るとけっきょく損をするというお話しです。
|
||||
</p>
|
||||
<p>
|
||||
おしまい
|
||||
</p>
|
||||
<div>
|
||||
<p></p></div>
|
||||
<p><span><img src="http://fakehost/gazou/pc_gazou/all/top_bana/back_logo_r.gif" alt="前のページへ戻る" name="Image10" width="175" height="32" id="Image10"></span></p></div>
|
||||
</td>
|
||||
<td>
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1">
|
||||
</td>
|
||||
<td>
|
||||
<table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_1.gif" width="7" height="7">
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<img src="http://fakehost/366/logo_bana/corner_2.gif" width="7" height="7">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table readabilityDataTable="1">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>1月 1日の豆知識</b></span><span size="-2"><u><p>
|
||||
366日への旅</p></u></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97" width="1" height="1"><b><span size="-1">きょうの記念日</span></b><a href="http://fakehost/366/kinenbi/pc/01gatu/1_01.htm"><span size="-1">元旦</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"><b><span size="-1">きょうの誕生花</span></b><a href="http://fakehost/366/hana/pc/01gatu/1_01.htm"><span size="-1">松(まつ)</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの誕生日・出来事</span></b><a href="http://fakehost/366/birthday/pc/01gatu/1_01.htm"><span size="-1">1949年 Mr.マリック(マジシャン)</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">恋の誕生日占い</span></b><a href="http://fakehost/sakura/uranai/birthday/01/01.html"><span size="-1">自分の考えをしっかりと持った女の子。</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">なぞなぞ小学校</span></b><a href="http://fakehost/nazonazo/new/2012/04/02.html"><span size="-1">○(丸)を取ったらお母さんになってしまう男の人は?</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">あこがれの職業紹介</span></b><a href="http://fakehost/sakura/navi/work/2017/041.html"><span size="-1">歌手</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">恋の魔法とおまじない</span></b> 001<a href="http://fakehost/omajinai/new/2012/00/re01.html"><span size="-1">両思いになれる おまじない</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"> <b>1月 1日の童話・昔話</b><u><span size="-2"><p>
|
||||
福娘童話集</p></span></u></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの日本昔話</span></b><a href="http://fakehost/douwa/pc/jap/01/01.htm"><span size="-1">ネコがネズミを追いかける訳</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの世界昔話<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"></span></b><a href="http://fakehost/douwa/pc/world/01/01a.htm"><span size="-1">モンゴルの十二支話</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="file:///C|/Documents%20and%20Settings/%E7%A6%8F%E5%A8%98note/%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97/company_website15/image/spacer.gif" width="1" height="1"><b><span size="-1">きょうの日本民話</span></b><a href="http://fakehost/douwa/pc/minwa/01/01c.html"><span size="-1">仕事の取替えっこ</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうのイソップ童話</span></b><a href="http://fakehost/douwa/pc/aesop/01/01.htm"><span size="-1">欲張りなイヌ</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの江戸小話</span></b><a href="http://fakehost/douwa/pc/kobanashi/01/01.htm"><span size="-1">ぞうきんとお年玉</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">きょうの百物語</span></b><a href="http://fakehost/douwa/pc/kaidan/01/01.htm"><span size="-1">百物語の幽霊</span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table readabilityDataTable="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<b><span size="-1">福娘のサイト</span></b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>366日への旅</b><p><a href="http://hukumusume.com/366/">毎日の記念日・誕生花 ・有名人の誕生日と性格判断</a></p></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>福娘童話集</b><p><a href="http://hukumusume.com/douwa/">世界と日本の童話と昔話</a></p></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>女の子応援サイト -さくら-</b><p><a href="http://hukumusume.com/sakura/index.html">誕生日占い、お仕事紹介、おまじない、など</a></p></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>子どもの病気相談所</b><p><a href="http://hukumusume.com/my_baby/sick/">病気検索と対応方法、症状から検索するWEB問診</a></p></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span size="-1"><b>世界60秒巡り</b><p><a href="http://hukumusume.com/366/world/">国旗国歌や世界遺産など、世界の国々の豆知識</a></p></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</div>
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"0": "http:\/\/www.iab.com\/wp-content\/uploads\/2015\/10\/getting-lean-with-digital-ad-ux-300x250.jpg",
|
||||
"2": "http:\/\/www.iab.com\/wp-content\/uploads\/2015\/05\/auto-draft-16-150x150.jpg"
|
||||
}
|
||||
[
|
||||
"http:\/\/www.iab.com\/wp-content\/uploads\/2015\/10\/getting-lean-with-digital-ad-ux-300x250.jpg",
|
||||
"http:\/\/www.iab.com\/wp-content\/uploads\/2015\/05\/auto-draft-16-150x150.jpg"
|
||||
]
|
|
@ -1,4 +1,3 @@
|
|||
<div>
|
||||
<div>
|
||||
<p>We messed up. As technologists, tasked with delivering content and services to users, we lost track of the user experience.</p>
|
||||
<p>Twenty years ago we saw an explosion of websites, built by developers around the world, providing all forms of content. This was the beginning of an age of enlightenment, the intersection of content and technology. Many of us in the technical field felt compelled, and even empowered, to produce information as the distribution means for mass communication were no longer restricted by a high barrier to entry.</p>
|
||||
|
@ -9,7 +8,7 @@
|
|||
<p>Through our pursuit of further automation and maximization of margins during the industrial age of media technology, we built advertising technology to optimize publishers’ yield of marketing budgets that had eroded after the last recession. Looking back now, our scraping of dimes may have cost us dollars in consumer loyalty. The fast, scalable systems of targeting users with ever-heftier advertisements have slowed down the public internet and drained more than a few batteries. We were so clever and so good at it that we over-engineered the capabilities of the plumbing laid down by, well, ourselves. This steamrolled the users, depleted their devices, and tried their patience.</p>
|
||||
<p>The rise of ad blocking poses a threat to the internet and could potentially drive users to an enclosed platform world dominated by a few companies. We have let the fine equilibrium of content, commerce, and technology get out of balance in the open web. We had, and still do have, a responsibility to educate the business side, and in some cases to push back. We lost sight of our social and ethical responsibility to provide a safe, usable experience for anyone and everyone wanting to consume the content of their choice.</p>
|
||||
<p>We need to bring that back into alignment, starting right now.</p>
|
||||
<p><a href="http://www.iab.com/wp-content/uploads/2015/10/getting-lean-with-digital-ad-ux.jpg"><img alt="Getting LEAN with Digital Ad UX" height="250" src="http://www.iab.com/wp-content/uploads/2015/10/getting-lean-with-digital-ad-ux-300x250.jpg" width="300"></img></a>Today, the IAB Tech Lab is launching the L.E.A.N. Ads program. Supported by the Executive Committee of the IAB Tech Lab Board, IABs around the world, and hundreds of member companies, L.E.A.N. stands for Light, Encrypted, Ad choice supported, Non-invasive ads. These are principles that will help guide the next phases of advertising technical standards for the global digital advertising supply chain.</p>
|
||||
<p><a href="http://www.iab.com/wp-content/uploads/2015/10/getting-lean-with-digital-ad-ux.jpg"><img width="300" height="250" alt="Getting LEAN with Digital Ad UX" src="http://www.iab.com/wp-content/uploads/2015/10/getting-lean-with-digital-ad-ux-300x250.jpg"></a>Today, the IAB Tech Lab is launching the L.E.A.N. Ads program. Supported by the Executive Committee of the IAB Tech Lab Board, IABs around the world, and hundreds of member companies, L.E.A.N. stands for Light, Encrypted, Ad choice supported, Non-invasive ads. These are principles that will help guide the next phases of advertising technical standards for the global digital advertising supply chain.</p>
|
||||
<p>As with any other industry, standards should be created by non-profit standards-setting bodies, with many diverse voices providing input. We will invite all parties for public comment, and make sure consumer interest groups have the opportunity to provide input.</p>
|
||||
<p>L.E.A.N. Ads do not replace the current advertising standards many consumers still enjoy and engage with while consuming content on our sites across all IP enabled devices. Rather, these principles will guide an alternative set of standards that provide choice for marketers, content providers, and consumers.</p>
|
||||
<p>Among the many areas of concentration, we must also address frequency capping on retargeting in Ad Tech and make sure a user is targeted appropriately before, but never AFTER they make a purchase. If we are so good at reach and scale, we can be just as good, if not better, at moderation. Additionally, we must address volume of ads per page as well as continue on the path to viewability. The dependencies here are critical to an optimized user experience.</p>
|
||||
|
@ -18,13 +17,13 @@
|
|||
<p>Finally, we must do this in an increasingly fragmented market, across screens. We must do this in environments where entire sites are blocked, purposefully or not. Yes, it is disappointing that our development efforts will have to manage with multiple frameworks while we work to supply the economic engine to sustain an open internet. However, our goal is still to provide diverse content and voices to as many connected users as possible around the world.</p>
|
||||
<p>That is user experience.</p>
|
||||
|
||||
<p>IAB Tech Lab Members can join the IAB Tech Lab Ad Blocking Working Group, please email <a href="mailto:adblocking@iab.com">adblocking@iab.com</a> for more information.</p><p>Read <a href="http://www.iab.com/insights/ad-blocking/" target="_blank">more about ad blocking here</a>.</p>
|
||||
</div>
|
||||
</div><div id="post-author"><div>
|
||||
<figure><img alt="Auto Draft 14" src="http://www.iab.com/wp-content/uploads/2015/05/auto-draft-16-150x150.jpg"></img></figure><div>
|
||||
<p>IAB Tech Lab Members can join the IAB Tech Lab Ad Blocking Working Group, please email <a href="mailto:adblocking@iab.com">adblocking@iab.com</a> for more information.</p>
|
||||
<p>Read <a target="_blank" href="http://www.iab.com/insights/ad-blocking/">more about ad blocking here</a>.</p>
|
||||
</div><div id="post-author">
|
||||
<figure><img alt="Auto Draft 14" src="http://www.iab.com/wp-content/uploads/2015/05/auto-draft-16-150x150.jpg"></figure>
|
||||
<div>
|
||||
<h4>About the author</h4>
|
||||
<p><strong>Scott Cunningham</strong></p>
|
||||
<p>Senior Vice President of Technology and Ad Operations at IAB, and General Manager of the IAB Tech Lab</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,6 +1,10 @@
|
|||
<div>
|
||||
|
||||
<span>[<a href="http://fakehost/test/../html/" title="Document search and retrieval page">Docs</a>] [<a href="https://tools.ietf.org/id/draft-dejong-remotestorage-04.txt" title="Plaintext version of this document">txt</a>|<a href="http://fakehost/pdf/draft-dejong-remotestorage-04.txt" title="PDF version of this document">pdf</a>] [<a href="https://datatracker.ietf.org/doc/draft-dejong-remotestorage" title="IESG Datatracker information for this document">Tracker</a>] [<a href="mailto:draft-dejong-remotestorage@tools.ietf.org?subject=draft-dejong-remotestorage%20" title="Send email to the document authors">Email</a>] [<a href="http://fakehost/rfcdiff?difftype=--hwdiff&url2=draft-dejong-remotestorage-04.txt" title="Inline diff (wdiff)">Diff1</a>] [<a href="http://fakehost/rfcdiff?url2=draft-dejong-remotestorage-04.txt" title="Side-by-side diff">Diff2</a>] [<a href="http://fakehost/idnits?url=https://tools.ietf.org/id/draft-dejong-remotestorage-04.txt" title="Run an idnits check of this document">Nits</a>] </span><br></br><span> </span><br></br><span>Versions: <a href="http://fakehost/test/draft-dejong-remotestorage-00">00</a> <a href="http://fakehost/test/draft-dejong-remotestorage-01">01</a> <a href="http://fakehost/test/draft-dejong-remotestorage-02">02</a> <a href="http://fakehost/test/draft-dejong-remotestorage-03">03</a> <a href="http://fakehost/test/draft-dejong-remotestorage-04">04</a> </span><br></br><span> </span><br></br><pre>INTERNET DRAFT Michiel B. de Jong
|
||||
<span>[<a href="http://fakehost/html/" title="Document search and retrieval page">Docs</a>] [<a href="https://tools.ietf.org/id/draft-dejong-remotestorage-04.txt" title="Plaintext version of this document">txt</a>|<a href="http://fakehost/pdf/draft-dejong-remotestorage-04.txt" title="PDF version of this document">pdf</a>] [<a href="https://datatracker.ietf.org/doc/draft-dejong-remotestorage" title="IESG Datatracker information for this document">Tracker</a>] [<a href="mailto:draft-dejong-remotestorage@tools.ietf.org?subject=draft-dejong-remotestorage%20" title="Send email to the document authors">Email</a>] [<a href="http://fakehost/rfcdiff?difftype=--hwdiff&url2=draft-dejong-remotestorage-04.txt" title="Inline diff (wdiff)">Diff1</a>] [<a href="http://fakehost/rfcdiff?url2=draft-dejong-remotestorage-04.txt" title="Side-by-side diff">Diff2</a>] [<a href="http://fakehost/idnits?url=https://tools.ietf.org/id/draft-dejong-remotestorage-04.txt" title="Run an idnits check of this document">Nits</a>] </span><br>
|
||||
<span> </span><br>
|
||||
<span>Versions: <a href="http://fakehost/test/draft-dejong-remotestorage-00">00</a> <a href="http://fakehost/test/draft-dejong-remotestorage-01">01</a> <a href="http://fakehost/test/draft-dejong-remotestorage-02">02</a> <a href="http://fakehost/test/draft-dejong-remotestorage-03">03</a> <a href="http://fakehost/test/draft-dejong-remotestorage-04">04</a> </span><br>
|
||||
<span> </span><br>
|
||||
<pre>INTERNET DRAFT Michiel B. de Jong
|
||||
Document: <a href="http://fakehost/test/draft-dejong-remotestorage-04">draft-dejong-remotestorage-04</a> IndieHosters
|
||||
F. Kooman
|
||||
Intended Status: Proposed Standard (independent)
|
||||
|
@ -53,7 +57,7 @@ Copyright Notice
|
|||
|
||||
|
||||
<span>de Jong [Page 1]</span>
|
||||
</pre><pre><a href="#page-2" id="page-2" name="page-2"> </a>
|
||||
</pre><pre><a name="page-2" id="page-2" href="#page-2"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -89,7 +93,7 @@ Table of Contents
|
|||
<a href="#section-18">18</a>. Authors' addresses............................................<a href="#page-22">22</a>
|
||||
|
||||
|
||||
<span><a href="#section-1" name="section-1">1</a>. Introduction</span>
|
||||
<span><a name="section-1" href="#section-1">1</a>. Introduction</span>
|
||||
|
||||
Many services for data storage are available over the internet. This
|
||||
specification describes a vendor-independent interface for such
|
||||
|
@ -103,7 +107,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 2]</span>
|
||||
</pre><pre><a href="#page-3" id="page-3" name="page-3"> </a>
|
||||
</pre><pre><a name="page-3" id="page-3" href="#page-3"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -122,7 +126,7 @@ Table of Contents
|
|||
The exact details of these four actions are described in this
|
||||
specification.
|
||||
|
||||
<span><a href="#section-2" name="section-2">2</a>. Terminology</span>
|
||||
<span><a name="section-2" href="#section-2">2</a>. Terminology</span>
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
|
@ -135,7 +139,7 @@ Table of Contents
|
|||
implement the general requirement when such failure would result in
|
||||
interoperability failure.
|
||||
|
||||
<span><a href="#section-3" name="section-3">3</a>. Storage model</span>
|
||||
<span><a name="section-3" href="#section-3">3</a>. Storage model</span>
|
||||
|
||||
The server stores data in nodes that form a tree structure.
|
||||
Internal nodes are called 'folders' and leaf nodes are called
|
||||
|
@ -153,7 +157,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 3]</span>
|
||||
</pre><pre><a href="#page-4" id="page-4" name="page-4"> </a>
|
||||
</pre><pre><a name="page-4" id="page-4" href="#page-4"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -163,7 +167,7 @@ Table of Contents
|
|||
* content length
|
||||
* content
|
||||
|
||||
<span><a href="#section-4" name="section-4">4</a>. Requests</span>
|
||||
<span><a name="section-4" href="#section-4">4</a>. Requests</span>
|
||||
|
||||
Client-to-server requests SHOULD be made over https [<a href="#ref-HTTPS">HTTPS</a>], and
|
||||
servers MUST comply with HTTP/1.1 [<a href="#ref-HTTP">HTTP</a>]. Specifically, they
|
||||
|
@ -203,7 +207,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 4]</span>
|
||||
</pre><pre><a href="#page-5" id="page-5" name="page-5"> </a>
|
||||
</pre><pre><a name="page-5" id="page-5" href="#page-5"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -253,7 +257,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 5]</span>
|
||||
</pre><pre><a href="#page-6" id="page-6" name="page-6"> </a>
|
||||
</pre><pre><a name="page-6" id="page-6" href="#page-6"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -303,11 +307,11 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 6]</span>
|
||||
</pre><pre><a href="#page-7" id="page-7" name="page-7"> </a>
|
||||
</pre><pre><a name="page-7" id="page-7" href="#page-7"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
<span><a href="#section-5" name="section-5">5</a>. Response codes</span>
|
||||
<span><a name="section-5" href="#section-5">5</a>. Response codes</span>
|
||||
|
||||
Response codes SHOULD be given as defined by [HTTP, <a href="#section-6">section 6</a>] and
|
||||
[BEARER, <a href="#section-3.1">section 3.1</a>]. The following is a non-normative checklist
|
||||
|
@ -340,7 +344,7 @@ Table of Contents
|
|||
Clients SHOULD also handle the case where a response takes too long
|
||||
to arrive, or where no response is received at all.
|
||||
|
||||
<span><a href="#section-6" name="section-6">6</a>. Versioning</span>
|
||||
<span><a name="section-6" href="#section-6">6</a>. Versioning</span>
|
||||
|
||||
All successful requests MUST return an 'ETag' header [<a href="#ref-HTTP">HTTP</a>] with, in
|
||||
the case of GET, the current version, in the case of PUT, the new
|
||||
|
@ -353,7 +357,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 7]</span>
|
||||
</pre><pre><a href="#page-8" id="page-8" name="page-8"> </a>
|
||||
</pre><pre><a name="page-8" id="page-8" href="#page-8"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -370,14 +374,14 @@ Table of Contents
|
|||
A provider MAY offer version rollback functionality to its users,
|
||||
but this specification does not define the user interface for that.
|
||||
|
||||
<span><a href="#section-7" name="section-7">7</a>. CORS headers</span>
|
||||
<span><a name="section-7" href="#section-7">7</a>. CORS headers</span>
|
||||
|
||||
All responses MUST carry CORS headers [<a href="#ref-CORS">CORS</a>]. The server MUST also
|
||||
reply to OPTIONS requests as per CORS. For GET requests, a wildcard
|
||||
origin MAY be returned, but for PUT and DELETE requests, the
|
||||
response MUST echo back the Origin header sent by the client.
|
||||
|
||||
<span><a href="#section-8" name="section-8">8</a>. Session description</span>
|
||||
<span><a name="section-8" href="#section-8">8</a>. Session description</span>
|
||||
|
||||
The information that a client needs to receive in order to be able
|
||||
to connect to a server SHOULD reach the client as described in the
|
||||
|
@ -403,7 +407,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 8]</span>
|
||||
</pre><pre><a href="#page-9" id="page-9" name="page-9"> </a>
|
||||
</pre><pre><a name="page-9" id="page-9" href="#page-9"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -418,7 +422,7 @@ Table of Contents
|
|||
* https://storage.example.com/bob/public/documents/
|
||||
* https://storage.example.com/bob/public/documents/draft.txt
|
||||
|
||||
<span><a href="#section-9" name="section-9">9</a>. Bearer tokens and access control</span>
|
||||
<span><a name="section-9" href="#section-9">9</a>. Bearer tokens and access control</span>
|
||||
|
||||
A bearer token represents one or more access scopes. These access
|
||||
scopes are represented as strings of the form <module> <level>,
|
||||
|
@ -453,12 +457,12 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 9]</span>
|
||||
</pre><pre><a href="#page-10" id="page-10" name="page-10"> </a>
|
||||
</pre><pre><a name="page-10" id="page-10" href="#page-10"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
||||
<span><a href="#section-10" name="section-10">10</a>. Application-first bearer token issuance</span>
|
||||
<span><a name="section-10" href="#section-10">10</a>. Application-first bearer token issuance</span>
|
||||
|
||||
To make a remoteStorage server available as 'the remoteStorage of
|
||||
<account> at <host>', exactly one link of the following format
|
||||
|
@ -503,7 +507,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 10]</span>
|
||||
</pre><pre><a href="#page-11" id="page-11" name="page-11"> </a>
|
||||
</pre><pre><a name="page-11" id="page-11" href="#page-11"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -533,7 +537,7 @@ Table of Contents
|
|||
client_id parameter in favor of relying on the redirect_uri
|
||||
parameter for client identification.
|
||||
|
||||
<span><a href="#section-11" name="section-11">11</a>. Storage-first bearer token issuance</span>
|
||||
<span><a name="section-11" href="#section-11">11</a>. Storage-first bearer token issuance</span>
|
||||
|
||||
The provider MAY also present a dashboard to the user, where they
|
||||
have some way to add open web app manifests [<a href="#ref-MANIFEST">MANIFEST</a>]. Adding a
|
||||
|
@ -553,7 +557,7 @@ Table of Contents
|
|||
|
||||
|
||||
<span>de Jong [Page 11]</span>
|
||||
</pre><pre><a href="#page-12" id="page-12" name="page-12"> </a>
|
||||
</pre><pre><a name="page-12" id="page-12" href="#page-12"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -591,19 +595,19 @@ Table of Contents
|
|||
debug tool, thus bypassing the need for an OAuth dance. Clients
|
||||
SHOULD NOT rely on this in production.
|
||||
|
||||
<span><a href="#section-12" name="section-12">12</a>. Example wire transcripts</span>
|
||||
<span><a name="section-12" href="#section-12">12</a>. Example wire transcripts</span>
|
||||
|
||||
The following examples are not normative ("\" indicates a line was
|
||||
wrapped).
|
||||
|
||||
<span><a href="#section-12.1" name="section-12.1">12.1</a>. WebFinger</span>
|
||||
<span><a name="section-12.1" href="#section-12.1">12.1</a>. WebFinger</span>
|
||||
|
||||
In application-first, an in-browser application might issue the
|
||||
following request, using XMLHttpRequest and CORS:
|
||||
|
||||
|
||||
<span>de Jong [Page 12]</span>
|
||||
</pre><pre><a href="#page-13" id="page-13" name="page-13"> </a>
|
||||
</pre><pre><a name="page-13" id="page-13" href="#page-13"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -643,7 +647,7 @@ motestorage-04",
|
|||
}]
|
||||
}
|
||||
|
||||
<span><a href="#section-12.2" name="section-12.2">12.2</a>. OAuth dialog form</span>
|
||||
<span><a name="section-12.2" href="#section-12.2">12.2</a>. OAuth dialog form</span>
|
||||
|
||||
Once the in-browser application has discovered the server's OAuth
|
||||
end-point, it will typically redirect the user to this URL, in
|
||||
|
@ -653,7 +657,7 @@ motestorage-04",
|
|||
|
||||
|
||||
<span>de Jong [Page 13]</span>
|
||||
</pre><pre><a href="#page-14" id="page-14" name="page-14"> </a>
|
||||
</pre><pre><a name="page-14" id="page-14" href="#page-14"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -673,7 +677,7 @@ unhosted.5apps.com&response_type=token HTTP/1.1
|
|||
<title>Allow access?</title>
|
||||
...
|
||||
|
||||
<span><a href="#section-12.3" name="section-12.3">12.3</a>. OAuth dialog form submission</span>
|
||||
<span><a name="section-12.3" href="#section-12.3">12.3</a>. OAuth dialog form submission</span>
|
||||
|
||||
When the user submits the form, the request would look something
|
||||
like this:
|
||||
|
@ -698,12 +702,12 @@ low
|
|||
Location:https://drinks-unhosted.5apps.com/#access_token=j2YnGt\
|
||||
XjzzzHNjkd1CJxoQubA1o%3D&token_type=bearer&state=
|
||||
|
||||
<span><a href="#section-12.4" name="section-12.4">12.4</a>. OPTIONS preflight</span>
|
||||
<span><a name="section-12.4" href="#section-12.4">12.4</a>. OPTIONS preflight</span>
|
||||
|
||||
|
||||
|
||||
<span>de Jong [Page 14]</span>
|
||||
</pre><pre><a href="#page-15" id="page-15" name="page-15"> </a>
|
||||
</pre><pre><a name="page-15" id="page-15" href="#page-15"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -726,7 +730,7 @@ XjzzzHNjkd1CJxoQubA1o%3D&token_type=bearer&state=
|
|||
Access-Control-Allow-Headers: Authorization, Content-Length, Co\
|
||||
ntent-Type, Origin, X-Requested-With, If-Match, If-None-Match
|
||||
|
||||
<span><a href="#section-12.5" name="section-12.5">12.5</a>. Initial PUT</span>
|
||||
<span><a name="section-12.5" href="#section-12.5">12.5</a>. Initial PUT</span>
|
||||
|
||||
An initial PUT may contain an 'If-None-Match: *' header, like this:
|
||||
|
||||
|
@ -749,11 +753,11 @@ ntent-Type, Origin, X-Requested-With, If-Match, If-None-Match
|
|||
Access-Control-Allow-Origin: <a href="https://drinks-unhosted.5apps.com">https://drinks-unhosted.5apps.com</a>
|
||||
ETag: "1382694045000"
|
||||
|
||||
<span><a href="#section-12.6" name="section-12.6">12.6</a>. Subsequent PUT</span>
|
||||
<span><a name="section-12.6" href="#section-12.6">12.6</a>. Subsequent PUT</span>
|
||||
|
||||
|
||||
<span>de Jong [Page 15]</span>
|
||||
</pre><pre><a href="#page-16" id="page-16" name="page-16"> </a>
|
||||
</pre><pre><a name="page-16" id="page-16" href="#page-16"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -779,7 +783,7 @@ e.io/spec/modules/myfavoritedrinks/drink"}
|
|||
Access-Control-Allow-Origin: <a href="https://drinks-unhosted.5apps.com">https://drinks-unhosted.5apps.com</a>
|
||||
ETag: "1382694048000"
|
||||
|
||||
<span><a href="#section-12.7" name="section-12.7">12.7</a>. GET</span>
|
||||
<span><a name="section-12.7" href="#section-12.7">12.7</a>. GET</span>
|
||||
|
||||
A GET request would also include the bearer token, and optionally
|
||||
an If-None-Match header:
|
||||
|
@ -803,7 +807,7 @@ e.io/spec/modules/myfavoritedrinks/drink"}
|
|||
|
||||
|
||||
<span>de Jong [Page 16]</span>
|
||||
</pre><pre><a href="#page-17" id="page-17" name="page-17"> </a>
|
||||
</pre><pre><a name="page-17" id="page-17" href="#page-17"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -838,7 +842,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
HTTP/1.1 404 Not Found
|
||||
Access-Control-Allow-Origin: <a href="https://drinks-unhosted.5apps.com">https://drinks-unhosted.5apps.com</a>
|
||||
|
||||
<span><a href="#section-12.8" name="section-12.8">12.8</a>. DELETE</span>
|
||||
<span><a name="section-12.8" href="#section-12.8">12.8</a>. DELETE</span>
|
||||
|
||||
A DELETE request may look like this:
|
||||
|
||||
|
@ -853,7 +857,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
|
||||
|
||||
<span>de Jong [Page 17]</span>
|
||||
</pre><pre><a href="#page-18" id="page-18" name="page-18"> </a>
|
||||
</pre><pre><a name="page-18" id="page-18" href="#page-18"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -863,7 +867,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
Access-Control-Allow-Origin: <a href="https://drinks-unhosted.5apps.com">https://drinks-unhosted.5apps.com</a>
|
||||
ETag: "1382694048000"
|
||||
|
||||
<span><a href="#section-13" name="section-13">13</a>. Distributed versioning</span>
|
||||
<span><a name="section-13" href="#section-13">13</a>. Distributed versioning</span>
|
||||
|
||||
This section is non-normative, and is intended to explain some of
|
||||
the design choices concerning ETags and folder listings. At the
|
||||
|
@ -903,7 +907,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
|
||||
|
||||
<span>de Jong [Page 18]</span>
|
||||
</pre><pre><a href="#page-19" id="page-19" name="page-19"> </a>
|
||||
</pre><pre><a name="page-19" id="page-19" href="#page-19"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -925,7 +929,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
but it is up to whichever client discovers a given version
|
||||
conflict, to resolve it.
|
||||
|
||||
<span><a href="#section-14" name="section-14">14</a>. Security Considerations</span>
|
||||
<span><a name="section-14" href="#section-14">14</a>. Security Considerations</span>
|
||||
|
||||
To prevent man-in-the-middle attacks, the use of https instead of
|
||||
http is important for both the interface itself and all end-points
|
||||
|
@ -953,7 +957,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
|
||||
|
||||
<span>de Jong [Page 19]</span>
|
||||
</pre><pre><a href="#page-20" id="page-20" name="page-20"> </a>
|
||||
</pre><pre><a name="page-20" id="page-20" href="#page-20"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
@ -970,7 +974,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
The server SHOULD also detect and stop denial-of-service attacks
|
||||
that aim to overwhelm its interface with too much traffic.
|
||||
|
||||
<span><a href="#section-15" name="section-15">15</a>. IANA Considerations</span>
|
||||
<span><a name="section-15" href="#section-15">15</a>. IANA Considerations</span>
|
||||
|
||||
This document registers the 'remotestorage' link relation, as well
|
||||
as the following WebFinger properties:
|
||||
|
@ -980,7 +984,7 @@ charset=UTF-8","Content-Length":106}}}
|
|||
* "<a href="http://tools.ietf.org/html/rfc7233">http://tools.ietf.org/html/rfc7233</a>"
|
||||
* "<a href="http://remotestorage.io/spec/web-authoring">http://remotestorage.io/spec/web-authoring</a>"
|
||||
|
||||
<span><a href="#section-16" name="section-16">16</a>. Acknowledgements</span>
|
||||
<span><a name="section-16" href="#section-16">16</a>. Acknowledgements</span>
|
||||
|
||||
The authors would like to thank everybody who contributed to the
|
||||
development of this protocol, including Kenny Bentley, Javier Diaz,
|
||||
|
@ -993,95 +997,95 @@ charset=UTF-8","Content-Length":106}}}
|
|||
Rick van Rein, Mark Nottingham, Julian Reschke, and Markus
|
||||
Lanthaler, among many others.
|
||||
|
||||
<span><a href="#section-17" name="section-17">17</a>. References</span>
|
||||
<span><a name="section-17" href="#section-17">17</a>. References</span>
|
||||
|
||||
<span><a href="#section-17.1" name="section-17.1">17.1</a>. Normative References</span>
|
||||
<span><a name="section-17.1" href="#section-17.1">17.1</a>. Normative References</span>
|
||||
|
||||
[<a id="ref-WORDS" name="ref-WORDS">WORDS</a>]
|
||||
[<a name="ref-WORDS" id="ref-WORDS">WORDS</a>]
|
||||
Bradner, S., "Key words for use in RFCs to Indicate Requirement
|
||||
Levels", <a href="http://fakehost/test/bcp14">BCP 14</a>, <a href="http://fakehost/test/rfc2119">RFC 2119</a>, March 1997.
|
||||
|
||||
|
||||
<span>de Jong [Page 20]</span>
|
||||
</pre><pre><a href="#page-21" id="page-21" name="page-21"> </a>
|
||||
</pre><pre><a name="page-21" id="page-21" href="#page-21"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
|
||||
[<a id="ref-IRI" name="ref-IRI">IRI</a>]
|
||||
[<a name="ref-IRI" id="ref-IRI">IRI</a>]
|
||||
Duerst, M., "Internationalized Resource Identifiers (IRIs)",
|
||||
<a href="http://fakehost/test/rfc3987">RFC 3987</a>, January 2005.
|
||||
|
||||
[<a id="ref-WEBFINGER" name="ref-WEBFINGER">WEBFINGER</a>]
|
||||
[<a name="ref-WEBFINGER" id="ref-WEBFINGER">WEBFINGER</a>]
|
||||
Jones, P., Salguerio, G., Jones, M, and Smarr, J.,
|
||||
"WebFinger", <a href="http://fakehost/test/rfc7033">RFC7033</a>, September 2013.
|
||||
|
||||
[<a id="ref-OAUTH" name="ref-OAUTH">OAUTH</a>]
|
||||
[<a name="ref-OAUTH" id="ref-OAUTH">OAUTH</a>]
|
||||
"<a href="#section-4.2">Section 4.2</a>: Implicit Grant", in: Hardt, D. (ed), "The OAuth
|
||||
2.0 Authorization Framework", <a href="http://fakehost/test/rfc6749">RFC6749</a>, October 2012.
|
||||
|
||||
<span><a href="#section-17.2" name="section-17.2">17.2</a>. Informative References</span>
|
||||
<span><a name="section-17.2" href="#section-17.2">17.2</a>. Informative References</span>
|
||||
|
||||
[<a id="ref-HTTPS" name="ref-HTTPS">HTTPS</a>]
|
||||
[<a name="ref-HTTPS" id="ref-HTTPS">HTTPS</a>]
|
||||
Rescorla, E., "HTTP Over TLS", <a href="http://fakehost/test/rfc2818">RFC2818</a>, May 2000.
|
||||
|
||||
[<a id="ref-HTTP" name="ref-HTTP">HTTP</a>]
|
||||
[<a name="ref-HTTP" id="ref-HTTP">HTTP</a>]
|
||||
Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
|
||||
Semantics and Content", <a href="http://fakehost/test/rfc7231">RFC7231</a>, June 2014.
|
||||
|
||||
[<a id="ref-COND" name="ref-COND">COND</a>]
|
||||
[<a name="ref-COND" id="ref-COND">COND</a>]
|
||||
Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
|
||||
Conditional Requests", <a href="http://fakehost/test/rfc7232">RFC7232</a>, June 2014.
|
||||
|
||||
[<a id="ref-RANGE" name="ref-RANGE">RANGE</a>]
|
||||
[<a name="ref-RANGE" id="ref-RANGE">RANGE</a>]
|
||||
Fielding et al., "Hypertext Transfer Protocol (HTTP/1.1):
|
||||
Conditional Requests", <a href="http://fakehost/test/rfc7233">RFC7233</a>, June 2014.
|
||||
|
||||
[<a id="ref-SPDY" name="ref-SPDY">SPDY</a>]
|
||||
[<a name="ref-SPDY" id="ref-SPDY">SPDY</a>]
|
||||
Mark Belshe, Roberto Peon, "SPDY Protocol - Draft 3.1", <a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">http://</a>
|
||||
<a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1</a>,
|
||||
September 2013.
|
||||
|
||||
[<a id="ref-JSON-LD" name="ref-JSON-LD">JSON-LD</a>]
|
||||
[<a name="ref-JSON-LD" id="ref-JSON-LD">JSON-LD</a>]
|
||||
M. Sporny, G. Kellogg, M. Lanthaler, "JSON-LD 1.0", W3C
|
||||
Proposed Recommendation,
|
||||
<a href="http://www.w3.org/TR/2014/REC-json-ld-20140116/">http://www.w3.org/TR/2014/REC-json-ld-20140116/</a>, January 2014.
|
||||
|
||||
[<a id="ref-CORS" name="ref-CORS">CORS</a>]
|
||||
[<a name="ref-CORS" id="ref-CORS">CORS</a>]
|
||||
van Kesteren, Anne (ed), "Cross-Origin Resource Sharing --
|
||||
W3C Candidate Recommendation 29 January 2013",
|
||||
|
||||
|
||||
<span>de Jong [Page 21]</span>
|
||||
</pre><pre><a href="#page-22" id="page-22" name="page-22"> </a>
|
||||
</pre><pre><a name="page-22" id="page-22" href="#page-22"> </a>
|
||||
<span>Internet-Draft remoteStorage December 2014</span>
|
||||
|
||||
|
||||
<a href="http://www.w3.org/TR/cors/">http://www.w3.org/TR/cors/</a>, January 2013.
|
||||
|
||||
[<a id="ref-MANIFEST" name="ref-MANIFEST">MANIFEST</a>]
|
||||
[<a name="ref-MANIFEST" id="ref-MANIFEST">MANIFEST</a>]
|
||||
Mozilla Developer Network (ed), "App manifest -- Revision
|
||||
330541", <a href="https://developer.mozilla.org/en-">https://developer.mozilla.org/en-</a>
|
||||
US/Apps/Build/Manifest$revision/566677, April 2014.
|
||||
|
||||
[<a id="ref-DATASTORE" name="ref-DATASTORE">DATASTORE</a>]
|
||||
[<a name="ref-DATASTORE" id="ref-DATASTORE">DATASTORE</a>]
|
||||
"WebAPI/DataStore", MozillaWiki, retrieved May 2014.
|
||||
<a href="https://wiki.mozilla.org/WebAPI/DataStore#Manifest">https://wiki.mozilla.org/WebAPI/DataStore#Manifest</a>
|
||||
|
||||
[<a id="ref-KERBEROS" name="ref-KERBEROS">KERBEROS</a>]
|
||||
[<a name="ref-KERBEROS" id="ref-KERBEROS">KERBEROS</a>]
|
||||
C. Neuman et al., "The Kerberos Network Authentication Service
|
||||
(V5)", <a href="http://fakehost/test/rfc4120">RFC4120</a>, July 2005.
|
||||
|
||||
[<a id="ref-BEARER" name="ref-BEARER">BEARER</a>]
|
||||
[<a name="ref-BEARER" id="ref-BEARER">BEARER</a>]
|
||||
M. Jones, D. Hardt, "The OAuth 2.0 Authorization Framework:
|
||||
Bearer Token Usage", <a href="http://fakehost/test/rfc6750">RFC6750</a>, October 2012.
|
||||
|
||||
[<a id="ref-AUTHORING" name="ref-AUTHORING">AUTHORING</a>]
|
||||
[<a name="ref-AUTHORING" id="ref-AUTHORING">AUTHORING</a>]
|
||||
"Using remoteStorage for web authoring", reSite wiki, retrieved
|
||||
September 2014. <a href="https://github.com/michielbdejong/resite/wiki">https://github.com/michielbdejong/resite/wiki</a>
|
||||
/Using-remoteStorage-for-web-authoring
|
||||
|
||||
<span><a href="#section-18" name="section-18">18</a>. Authors' addresses</span>
|
||||
<span><a name="section-18" href="#section-18">18</a>. Authors' addresses</span>
|
||||
|
||||
Michiel B. de Jong
|
||||
IndieHosters
|
||||
|
@ -1104,7 +1108,8 @@ charset=UTF-8","Content-Length":106}}}
|
|||
|
||||
de Jong [Page 22]
|
||||
|
||||
</pre><br></br><span><small><small>Html markup produced by rfcmarkup 1.111, available from
|
||||
</pre><br>
|
||||
<span><small><small>Html markup produced by rfcmarkup 1.111, available from
|
||||
<a href="https://tools.ietf.org/tools/rfcmarkup/">https://tools.ietf.org/tools/rfcmarkup/</a>
|
||||
</small></small></span>
|
||||
</div>
|
File diff suppressed because one or more lines are too long
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"0": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*sLDnS1UWEFIS33uLMxq3cw.jpeg",
|
||||
"1": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*sLDnS1UWEFIS33uLMxq3cw.jpeg",
|
||||
"2": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*3vIhkoHIzcxvUdijoCVx6w.png",
|
||||
"3": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*4gN1-fzOwCniw-DbqQjDeQ.jpeg",
|
||||
"4": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*2KPmZkIBUrhps-2uwDvYFQ.jpeg",
|
||||
"5": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*PU40bbbox2Ompc5I3RE99A.jpeg",
|
||||
"6": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*ohyycinH18fz98TCyUzVgQ.png",
|
||||
"7": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*mKvUNOAVQxl6atCbxbCZsg.jpeg",
|
||||
"8": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*knT10_FNVUmqQIBLnutmzQ.jpeg",
|
||||
"10": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*Vr61dyCTRwk6CemmVF8YAQ.jpeg",
|
||||
"11": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*a-1_13xE6_ErQ-QSlz6myw.jpeg",
|
||||
"13": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*IWXhtSsVv0gNnCwnDEXk-Q.jpeg",
|
||||
"14": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*NGcrjfkV0l37iQH2uyYjEw.jpeg",
|
||||
"15": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*WRlKt3q3mt7utmwxcbl3sQ.jpeg",
|
||||
"16": "https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*320_4I0lxbn5x3bx4XPI5Q.png"
|
||||
}
|
||||
[
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*sLDnS1UWEFIS33uLMxq3cw.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*sLDnS1UWEFIS33uLMxq3cw.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*3vIhkoHIzcxvUdijoCVx6w.png",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*4gN1-fzOwCniw-DbqQjDeQ.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*2KPmZkIBUrhps-2uwDvYFQ.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*PU40bbbox2Ompc5I3RE99A.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*ohyycinH18fz98TCyUzVgQ.png",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*mKvUNOAVQxl6atCbxbCZsg.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*knT10_FNVUmqQIBLnutmzQ.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*Vr61dyCTRwk6CemmVF8YAQ.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*a-1_13xE6_ErQ-QSlz6myw.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*IWXhtSsVv0gNnCwnDEXk-Q.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*NGcrjfkV0l37iQH2uyYjEw.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/2000\/1*WRlKt3q3mt7utmwxcbl3sQ.jpeg",
|
||||
"https:\/\/d262ilb51hltx0.cloudfront.net\/max\/800\/1*320_4I0lxbn5x3bx4XPI5Q.png"
|
||||
]
|
|
@ -1,58 +1,65 @@
|
|||
<div name="ef8c">
|
||||
<div>
|
||||
<figure name="b9ad" id="b9ad">
|
||||
<div>
|
||||
<section name="ef8c">
|
||||
<div>
|
||||
<div>
|
||||
<figure id="b9ad" name="b9ad"><div>
|
||||
|
||||
<p><img data-height="1402" data-image-id="1*sLDnS1UWEFIS33uLMxq3cw.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*sLDnS1UWEFIS33uLMxq3cw.jpeg"></img></p></div>
|
||||
</figure></div>
|
||||
<p><img data-image-id="1*sLDnS1UWEFIS33uLMxq3cw.jpeg" data-width="2100" data-height="1402" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*sLDnS1UWEFIS33uLMxq3cw.jpeg">
|
||||
</p></div>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
|
||||
<h4 data-align="center" id="9736" name="9736">Welcome to DoctorX’s Barcelona lab, where the drugs you bought online are tested for safety and purity. No questions asked.</h4>
|
||||
<h4 name="9736" id="9736" data-align="center">Welcome to DoctorX’s Barcelona lab, where the drugs you bought online are tested for safety and purity. No questions asked.</h4>
|
||||
|
||||
<figure id="7417" name="7417"><div>
|
||||
<figure name="7417" id="7417">
|
||||
<div>
|
||||
|
||||
<p><img data-action="zoom" data-action-value="1*3vIhkoHIzcxvUdijoCVx6w.png" data-height="24" data-image-id="1*3vIhkoHIzcxvUdijoCVx6w.png" data-width="1200" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*3vIhkoHIzcxvUdijoCVx6w.png"></img></p></div>
|
||||
</figure><p id="8a83" name="8a83">Standing at a table in a chemistry lab in Barcelona, Cristina Gil Lladanosa
|
||||
<p><img data-image-id="1*3vIhkoHIzcxvUdijoCVx6w.png" data-width="1200" data-height="24" data-action="zoom" data-action-value="1*3vIhkoHIzcxvUdijoCVx6w.png" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*3vIhkoHIzcxvUdijoCVx6w.png">
|
||||
</p></div>
|
||||
</figure>
|
||||
<p name="8a83" id="8a83">Standing at a table in a chemistry lab in Barcelona, Cristina Gil Lladanosa
|
||||
tears open a silver, smell-proof protective envelope. She slides out a
|
||||
transparent bag full of crystals. Around her, machines whir and hum, and
|
||||
other researchers mill around in long, white coats.</p>
|
||||
<p id="b675" name="b675">She is holding the lab’s latest delivery of a drug bought from the “deep
|
||||
<p name="b675" id="b675">She is holding the lab’s latest delivery of a drug bought from the “deep
|
||||
web,” the clandestine corner of the internet that isn’t reachable by normal
|
||||
search engines, and is home to some sites that require special software
|
||||
to access. Labeled as <a data-href="http://en.wikipedia.org/wiki/MDMA" href="http://en.wikipedia.org/wiki/MDMA" rel="nofollow">MDMA</a> (the street
|
||||
to access. Labeled as <a href="http://en.wikipedia.org/wiki/MDMA" data-href="http://en.wikipedia.org/wiki/MDMA" rel="nofollow">MDMA</a> (the street
|
||||
term is ecstasy), this sample has been shipped from Canada. Lladanosa and
|
||||
her colleague Iván Fornís Espinosa have also received drugs, anonymously,
|
||||
from people in China, Australia, Europe and the United States.</p>
|
||||
<p id="3c0b" name="3c0b">“Here we have speed, MDMA, cocaine, pills,” Lladanosa says, pointing to
|
||||
<p name="3c0b" id="3c0b">“Here we have speed, MDMA, cocaine, pills,” Lladanosa says, pointing to
|
||||
vials full of red, green, blue and clear solutions sitting in labeled boxes.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="c4e6" name="c4e6"><div>
|
||||
|
||||
<p><img data-height="1402" data-image-id="1*4gN1-fzOwCniw-DbqQjDeQ.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*4gN1-fzOwCniw-DbqQjDeQ.jpeg"></img></p></div>
|
||||
<figcaption>Cristina Gil Lladanosa, at the Barcelona testing lab | photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="c4e6" id="c4e6">
|
||||
<div>
|
||||
<p id="7a54" name="7a54">Since 2011, with the launch of <a data-href="http://en.wikipedia.org/wiki/Silk_Road_%28marketplace%29" href="http://en.wikipedia.org/wiki/Silk_Road_%28marketplace%29" rel="nofollow">Silk Road</a>, anybody has been able to safely buy illegal
|
||||
|
||||
<p><img data-image-id="1*4gN1-fzOwCniw-DbqQjDeQ.jpeg" data-width="2100" data-height="1402" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*4gN1-fzOwCniw-DbqQjDeQ.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Cristina Gil Lladanosa, at the Barcelona testing lab | photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="7a54" id="7a54">Since 2011, with the launch of <a href="http://en.wikipedia.org/wiki/Silk_Road_%28marketplace%29" data-href="http://en.wikipedia.org/wiki/Silk_Road_%28marketplace%29" rel="nofollow">Silk Road</a>, anybody has been able to safely buy illegal
|
||||
drugs from the deep web and have them delivered to their door. Though the
|
||||
FBI shut down that black market in October 2013, other outlets have emerged
|
||||
to fill its role. For the last 10 months the lab at which Lladanosa and
|
||||
Espinosa work has offered a paid testing service of those drugs. By sending
|
||||
in samples for analysis, users can know exactly what it is they are buying,
|
||||
and make a more informed decision about whether to ingest the substance.
|
||||
The group, called <a data-href="http://energycontrol.org/" href="http://energycontrol.org/" rel="nofollow">Energy Control</a>,
|
||||
The group, called <a href="http://energycontrol.org/" data-href="http://energycontrol.org/" rel="nofollow">Energy Control</a>,
|
||||
which has being running “harm reduction” programs since 1999, is the first
|
||||
to run a testing service explicitly geared towards verifying those purchases
|
||||
from the deep web.</p>
|
||||
<p id="4395" name="4395">Before joining Energy Control, Lladanosa briefly worked at a pharmacy,
|
||||
<p name="4395" id="4395">Before joining Energy Control, Lladanosa briefly worked at a pharmacy,
|
||||
whereas Espinosa spent 14 years doing drug analysis. Working at Energy
|
||||
Control is “more gratifying,” and “rewarding” than her previous jobs, Lladanosa
|
||||
told me. They also receive help from a group of volunteers, made up of
|
||||
a mixture of “squatters,” as Espinosa put it, and medical students, who
|
||||
prepare the samples for testing.</p>
|
||||
<p id="0c18" name="0c18">After weighing out the crystals, aggressively mixing it with methanol
|
||||
<p name="0c18" id="0c18">After weighing out the crystals, aggressively mixing it with methanol
|
||||
until dissolved, and delicately pouring the liquid into a tiny brown bottle,
|
||||
Lladanosa, a petite woman who is nearly engulfed by her lab coat, is now
|
||||
ready to test the sample. She loads a series of three trays on top of a
|
||||
|
@ -60,50 +67,61 @@
|
|||
A jungle of thick pipes hang from the lab’s ceiling behind it.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="559c" name="559c"><div>
|
||||
|
||||
<p><img data-height="1402" data-image-id="1*2KPmZkIBUrhps-2uwDvYFQ.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*2KPmZkIBUrhps-2uwDvYFQ.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="559c" id="559c">
|
||||
<div>
|
||||
<p id="1549" name="1549">“Chromatography separates all the substances,” Lladanosa says as she loads
|
||||
|
||||
<p><img data-image-id="1*2KPmZkIBUrhps-2uwDvYFQ.jpeg" data-width="2100" data-height="1402" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*2KPmZkIBUrhps-2uwDvYFQ.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="1549" id="1549">“Chromatography separates all the substances,” Lladanosa says as she loads
|
||||
the machine with an array of drugs sent from the deep web and local Spanish
|
||||
users. It can tell whether a sample is pure or contaminated, and if the
|
||||
latter, with what.</p>
|
||||
<p id="5d0f" name="5d0f">Rushes of hot air blow across the desk as the gas chromatograph blasts
|
||||
<p name="5d0f" id="5d0f">Rushes of hot air blow across the desk as the gas chromatograph blasts
|
||||
the sample at 280 degrees Celsius. Thirty minutes later the machine’s robotic
|
||||
arm automatically moves over to grip another bottle. The machine will continue
|
||||
cranking through the 150 samples in the trays for most of the work week.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="d6aa" name="d6aa"><div>
|
||||
|
||||
<p><img data-height="1241" data-image-id="1*PU40bbbox2Ompc5I3RE99A.jpeg" data-width="2013" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*PU40bbbox2Ompc5I3RE99A.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="d6aa" id="d6aa">
|
||||
<div>
|
||||
<p id="15e0" name="15e0">To get the drugs to Barcelona, a user mails at least 10 milligrams of
|
||||
|
||||
<p><img data-image-id="1*PU40bbbox2Ompc5I3RE99A.jpeg" data-width="2013" data-height="1241" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*PU40bbbox2Ompc5I3RE99A.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="15e0" id="15e0">To get the drugs to Barcelona, a user mails at least 10 milligrams of
|
||||
a substance to the offices of the Asociación Bienestar y Desarrollo, the
|
||||
non-government organization that oversees Energy Control. The sample then
|
||||
gets delivered to the testing service’s laboratory, at the Barcelona Biomedical
|
||||
Research Park, a futuristic, seven story building sitting metres away from
|
||||
the beach. Energy Control borrows its lab space from a biomedical research
|
||||
group for free.</p>
|
||||
<p id="2574" name="2574">The tests cost 50 Euro per sample. Users pay, not surprisingly, with Bitcoin.
|
||||
<p name="2574" id="2574">The tests cost 50 Euro per sample. Users pay, not surprisingly, with Bitcoin.
|
||||
In the post announcing Energy Control’s service on the deep web, the group
|
||||
promised that “All profits of this service are set aside of maintenance
|
||||
of this project.”</p>
|
||||
<p id="2644" name="2644">About a week after testing, those results are sent in a PDF to an email
|
||||
<p name="2644" id="2644">About a week after testing, those results are sent in a PDF to an email
|
||||
address provided by the anonymous client.</p>
|
||||
<p id="9f91" name="9f91">“The process is quite boring, because you are in a routine,” Lladanosa
|
||||
<p name="9f91" id="9f91">“The process is quite boring, because you are in a routine,” Lladanosa
|
||||
says. But one part of the process is consistently surprising: that moment
|
||||
when the results pop up on the screen. “Every time it’s something different.”
|
||||
For instance, one cocaine sample she had tested also contained phenacetin,
|
||||
a painkiller added to increase the product’s weight; lidocaine, an anesthetic
|
||||
that numbs the gums, giving the impression that the user is taking higher
|
||||
quality cocaine; and common caffeine.</p>
|
||||
<figure id="b821" name="b821"><div>
|
||||
<figure name="b821" id="b821">
|
||||
<div>
|
||||
|
||||
<p><img data-action="zoom" data-action-value="1*ohyycinH18fz98TCyUzVgQ.png" data-height="24" data-image-id="1*ohyycinH18fz98TCyUzVgQ.png" data-width="1200" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*ohyycinH18fz98TCyUzVgQ.png"></img></p></div>
|
||||
</figure><p id="39a6" name="39a6">The deep web drug lab is the brainchild of Fernando Caudevilla, a Spanish
|
||||
<p><img data-image-id="1*ohyycinH18fz98TCyUzVgQ.png" data-width="1200" data-height="24" data-action="zoom" data-action-value="1*ohyycinH18fz98TCyUzVgQ.png" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*ohyycinH18fz98TCyUzVgQ.png">
|
||||
</p></div>
|
||||
</figure>
|
||||
<p name="39a6" id="39a6">The deep web drug lab is the brainchild of Fernando Caudevilla, a Spanish
|
||||
physician who is better known as “DoctorX” on the deep web, a nickname
|
||||
given to him by his Energy Control co-workers because of his earlier writing
|
||||
about the history, risks and recreational culture of MDMA. In the physical
|
||||
|
@ -113,39 +131,43 @@
|
|||
harms of certain substances.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="eebc" name="eebc"><div>
|
||||
|
||||
<p><img data-height="1241" data-image-id="1*mKvUNOAVQxl6atCbxbCZsg.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*mKvUNOAVQxl6atCbxbCZsg.jpeg"></img></p></div>
|
||||
<figcaption>Fernando Caudevilla, AKA DoctorX. Photo: Joseph Cox</figcaption></figure></div>
|
||||
<figure name="eebc" id="eebc">
|
||||
<div>
|
||||
<p id="c099" name="c099">Caudevilla first ventured into Silk Road forums in April 2013. “I would
|
||||
|
||||
<p><img data-image-id="1*mKvUNOAVQxl6atCbxbCZsg.jpeg" data-width="2100" data-height="1241" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*mKvUNOAVQxl6atCbxbCZsg.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Fernando Caudevilla, AKA DoctorX. Photo: Joseph Cox</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="c099" id="c099">Caudevilla first ventured into Silk Road forums in April 2013. “I would
|
||||
like to contribute to this forum offering professional advice in topics
|
||||
related to drug use and health,” he wrote in an <a data-href="http://web.archive.org/web/20131015051405/https://dkn255hz262ypmii.onion.to/index.php?topic=147607.0" href="http://web.archive.org/web/20131015051405/https://dkn255hz262ypmii.onion.to/index.php?topic=147607.0" rel="nofollow">introductory post</a>,
|
||||
related to drug use and health,” he wrote in an <a href="http://web.archive.org/web/20131015051405/https://dkn255hz262ypmii.onion.to/index.php?topic=147607.0" data-href="http://web.archive.org/web/20131015051405/https://dkn255hz262ypmii.onion.to/index.php?topic=147607.0" rel="nofollow">introductory post</a>,
|
||||
using his DoctorX alias. Caudevilla offered to provide answers to questions
|
||||
that a typical doctor is not prepared, or willing, to respond to, at least
|
||||
not without a lecture or a judgment. “This advice cannot replace a complete
|
||||
face-to-face medical evaluation,” he wrote, “but I know how difficult it
|
||||
can be to talk frankly about these things.”</p>
|
||||
<p id="ff1d" name="ff1d">The requests flooded in. A diabetic asked what effect MDMA has on blood
|
||||
<p name="ff1d" id="ff1d">The requests flooded in. A diabetic asked what effect MDMA has on blood
|
||||
sugar; another what the risks of frequent psychedelic use were for a young
|
||||
person. Someone wanted to know whether amphetamine use should be avoided
|
||||
during lactation. In all, Fernando’s thread received over 50,000 visits
|
||||
and 300 questions before the FBI shut down Silk Road.</p>
|
||||
<p id="1f35" name="1f35">“He’s amazing. A gift to this community,” one user wrote on the Silk Road
|
||||
<p name="1f35" id="1f35">“He’s amazing. A gift to this community,” one user wrote on the Silk Road
|
||||
2.0 forum, a site that sprang up after the original. “His knowledge is
|
||||
invaluable, and never comes with any judgment.” Up until recently, Caudevilla
|
||||
answered questions on the marketplace “Evolution.” Last week, however,
|
||||
the administrators of that site <a data-href="http://motherboard.vice.com/read/one-of-the-darknets-biggest-markets-may-have-just-stole-all-its-users-bitcoin" href="http://motherboard.vice.com/read/one-of-the-darknets-biggest-markets-may-have-just-stole-all-its-users-bitcoin" rel="nofollow">pulled a scam</a>,
|
||||
the administrators of that site <a href="http://motherboard.vice.com/read/one-of-the-darknets-biggest-markets-may-have-just-stole-all-its-users-bitcoin" data-href="http://motherboard.vice.com/read/one-of-the-darknets-biggest-markets-may-have-just-stole-all-its-users-bitcoin" rel="nofollow">pulled a scam</a>,
|
||||
shutting the market down and escaping with an estimated $12 million worth
|
||||
of Bitcoin.</p>
|
||||
<p id="b20f" name="b20f">Caudevilla’s transition from dispensing advice to starting up a no-questions-asked
|
||||
<p name="b20f" id="b20f">Caudevilla’s transition from dispensing advice to starting up a no-questions-asked
|
||||
drug testing service came as a consequence of his experience on the deep
|
||||
web. He’d wondered whether he could help bring more harm reduction services
|
||||
to a marketplace without controls. The Energy Control project, as part
|
||||
of its mandate of educating drug users and preventing harm, had already
|
||||
been carrying out drug testing for local Spanish users since 2001, at music
|
||||
festivals, night clubs, or through a drop-in service at a lab in Madrid.</p>
|
||||
<p id="f739" name="f739">“I thought, we are doing this in Spain, why don’t we do an international
|
||||
<p name="f739" id="f739">“I thought, we are doing this in Spain, why don’t we do an international
|
||||
drug testing service?” Caudevilla told me when I visited the other Energy
|
||||
Control lab, in Madrid. Caudevilla, a stocky character with ear piercings
|
||||
and short, shaved hair, has eyes that light up whenever he discusses the
|
||||
|
@ -157,31 +179,38 @@
|
|||
transparency,” Caudevilla said. “We could not make mistakes,” he added.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="4058" name="4058"><div>
|
||||
|
||||
<p><img data-height="3141" data-image-id="1*knT10_FNVUmqQIBLnutmzQ.jpeg" data-width="4400" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*knT10_FNVUmqQIBLnutmzQ.jpeg"></img></p></div>
|
||||
<figcaption>Photo: Joseph Cox</figcaption></figure></div>
|
||||
<figure name="4058" id="4058">
|
||||
<div>
|
||||
<figure id="818c" name="818c"><div>
|
||||
|
||||
<p><img data-action="zoom" data-action-value="1*ohyycinH18fz98TCyUzVgQ.png" data-height="24" data-image-id="1*ohyycinH18fz98TCyUzVgQ.png" data-width="1200" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*ohyycinH18fz98TCyUzVgQ.png"></img></p></div>
|
||||
</figure><p id="7b5e" name="7b5e">While the Energy Control lab in Madrid lab only tests Spanish drugs from
|
||||
<p><img data-image-id="1*knT10_FNVUmqQIBLnutmzQ.jpeg" data-width="4400" data-height="3141" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*knT10_FNVUmqQIBLnutmzQ.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo: Joseph Cox</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<figure name="818c" id="818c">
|
||||
<div>
|
||||
|
||||
<p><img data-image-id="1*ohyycinH18fz98TCyUzVgQ.png" data-width="1200" data-height="24" data-action="zoom" data-action-value="1*ohyycinH18fz98TCyUzVgQ.png" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*ohyycinH18fz98TCyUzVgQ.png">
|
||||
</p></div>
|
||||
</figure>
|
||||
<p name="7b5e" id="7b5e">While the Energy Control lab in Madrid lab only tests Spanish drugs from
|
||||
various sources, it is the Barcelona location which vets the substances
|
||||
bought in the shadowy recesses of of the deep web. Caudevilla no longer
|
||||
runs it, having handed it over to his colleague Ana Muñoz. She maintains
|
||||
a presence on the deep web forums, answers questions from potential users,
|
||||
and sends back reports when they are ready.</p>
|
||||
<p id="0f0e" name="0f0e">The testing program exists in a legal grey area. The people who own the
|
||||
<p name="0f0e" id="0f0e">The testing program exists in a legal grey area. The people who own the
|
||||
Barcelona lab are accredited to experiment with and handle drugs, but Energy
|
||||
Control doesn’t have this permission itself, at least not in writing.</p>
|
||||
<p id="e002" name="e002">“We have a verbal agreement with the police and other authorities. They
|
||||
<p name="e002" id="e002">“We have a verbal agreement with the police and other authorities. They
|
||||
already know what we are doing,” Lladanosa tells me. It is a pact of mutual
|
||||
benefit. Energy Control provides the police with information on batches
|
||||
of drugs in Spain, whether they’re from the deep web or not, Espinosa says.
|
||||
They also contribute to the European Monitoring Centre for Drugs and Drug
|
||||
Addiction’s early warning system, a collaboration that attempts to spread
|
||||
information about dangerous drugs as quickly as possible.</p>
|
||||
<p id="db1b" name="db1b">By the time of my visit in February, Energy Control had received over
|
||||
<p name="db1b" id="db1b">By the time of my visit in February, Energy Control had received over
|
||||
150 samples from the deep web and have been receiving more at a rate of
|
||||
between 4 and 8 a week. Traditional drugs, such as cocaine and MDMA, make
|
||||
up about 70 percent of the samples tested, but the Barcelona lab has also
|
||||
|
@ -189,131 +218,150 @@
|
|||
synthetic cannabinoids, and even pills of Viagra.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="b885" name="b885"><div>
|
||||
|
||||
<p><img data-height="1402" data-image-id="1*Vr61dyCTRwk6CemmVF8YAQ.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*Vr61dyCTRwk6CemmVF8YAQ.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="b885" id="b885">
|
||||
<div>
|
||||
<p id="e76f" name="e76f">So it’s fair to make a tentative judgement on what people are paying for
|
||||
|
||||
<p><img data-image-id="1*Vr61dyCTRwk6CemmVF8YAQ.jpeg" data-width="2100" data-height="1402" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*Vr61dyCTRwk6CemmVF8YAQ.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="e76f" id="e76f">So it’s fair to make a tentative judgement on what people are paying for
|
||||
on the deep web. The verdict thus far? Overall, drugs on the deep web appear
|
||||
to be of much higher quality than those found on the street.</p>
|
||||
<p id="5352" name="5352">“In general, the cocaine is amazing,” says Caudevilla, saying that the
|
||||
<p name="5352" id="5352">“In general, the cocaine is amazing,” says Caudevilla, saying that the
|
||||
samples they’ve seen have purities climbing towards 80 or 90 percent, and
|
||||
some even higher. To get an idea of how unusual this is, take a look at
|
||||
the <a data-href="http://www.unodc.org/documents/wdr2014/Cocaine_2014_web.pdf" href="http://www.unodc.org/documents/wdr2014/Cocaine_2014_web.pdf" rel="nofollow">United Nations Office on Drugs and Crime World Drug Report 2014</a>,
|
||||
the <a href="http://www.unodc.org/documents/wdr2014/Cocaine_2014_web.pdf" data-href="http://www.unodc.org/documents/wdr2014/Cocaine_2014_web.pdf" rel="nofollow">United Nations Office on Drugs and Crime World Drug Report 2014</a>,
|
||||
which reports that the average quality of street cocaine in Spain is just
|
||||
over 40 percent, while in the United Kingdom it is closer to 30 percent.“We
|
||||
have found 100 percent [pure] cocaine,” he adds. “That’s really, really
|
||||
strange. That means that, technically, this cocaine has been purified,
|
||||
with clandestine methods.”</p>
|
||||
<p id="a71c" name="a71c">Naturally, identifying vendors who sell this top-of-the-range stuff is
|
||||
<p name="a71c" id="a71c">Naturally, identifying vendors who sell this top-of-the-range stuff is
|
||||
one of the reasons that people have sent samples to Energy Control. Caudevilla
|
||||
was keen to stress that, officially, Energy Control’s service “is not intended
|
||||
to be a control of drug quality,” meaning a vetting process for identifying
|
||||
the best sellers, but that is exactly how some people have been using it.</p>
|
||||
<p id="cb5b" name="cb5b">As one buyer on the Evolution market, elmo666, wrote to me over the site’s
|
||||
<p name="cb5b" id="cb5b">As one buyer on the Evolution market, elmo666, wrote to me over the site’s
|
||||
messaging system, “My initial motivations were selfish. My primary motivation
|
||||
was to ensure that I was receiving and continue to receive a high quality
|
||||
product, essentially to keep the vendor honest as far as my interactions
|
||||
with them went.”</p>
|
||||
<p id="d80d" name="d80d">Vendors on deep web markets advertise their product just like any other
|
||||
<p name="d80d" id="d80d">Vendors on deep web markets advertise their product just like any other
|
||||
outlet does, using flash sales, gimmicky giveaways and promises of drugs
|
||||
that are superior to those of their competitors. The claims, however, can
|
||||
turn out to be empty: despite the test results that show that deep web
|
||||
cocaine vendors typically sell product that is of a better quality than
|
||||
that found on the street, in plenty of cases, the drugs are nowhere near
|
||||
as pure as advertised.</p>
|
||||
<p id="36de" name="36de">“You won’t be getting anything CLOSE to what you paid for,” one user complained
|
||||
<p name="36de" id="36de">“You won’t be getting anything CLOSE to what you paid for,” one user complained
|
||||
about the cocaine from ‘Mirkov’, a vendor on Evolution. “He sells 65% not
|
||||
95%.”</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="8544" name="8544"><div>
|
||||
|
||||
<p><img data-height="1402" data-image-id="1*a-1_13xE6_ErQ-QSlz6myw.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*a-1_13xE6_ErQ-QSlz6myw.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="8544" id="8544">
|
||||
<div>
|
||||
<figure id="d521" name="d521"><div>
|
||||
|
||||
<p><img data-action="zoom" data-action-value="1*ohyycinH18fz98TCyUzVgQ.png" data-height="24" data-image-id="1*ohyycinH18fz98TCyUzVgQ.png" data-width="1200" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*ohyycinH18fz98TCyUzVgQ.png"></img></p></div>
|
||||
</figure><p id="126b" name="126b">Despite the prevalence of people using the service to gauge the quality
|
||||
<p><img data-image-id="1*a-1_13xE6_ErQ-QSlz6myw.jpeg" data-width="2100" data-height="1402" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*a-1_13xE6_ErQ-QSlz6myw.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<figure name="d521" id="d521">
|
||||
<div>
|
||||
|
||||
<p><img data-image-id="1*ohyycinH18fz98TCyUzVgQ.png" data-width="1200" data-height="24" data-action="zoom" data-action-value="1*ohyycinH18fz98TCyUzVgQ.png" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*ohyycinH18fz98TCyUzVgQ.png">
|
||||
</p></div>
|
||||
</figure>
|
||||
<p name="126b" id="126b">Despite the prevalence of people using the service to gauge the quality
|
||||
of what goes up their nose, many users send samples to Energy Control in
|
||||
the spirit of its original mission: keeping themselves alive and healthy.
|
||||
The worst case scenario from drugs purchased on the deep web is, well the
|
||||
worst case. That was the outcome when <a data-href="http://www.independent.co.uk/news/uk/crime/teenager-patrick-mcmullen-who-died-while-on-skype-had-bought-drugs-from-silk-road-8942329.html" href="http://www.independent.co.uk/news/uk/crime/teenager-patrick-mcmullen-who-died-while-on-skype-had-bought-drugs-from-silk-road-8942329.html" rel="nofollow">Patrick McMullen,</a> a
|
||||
worst case. That was the outcome when <a href="http://www.independent.co.uk/news/uk/crime/teenager-patrick-mcmullen-who-died-while-on-skype-had-bought-drugs-from-silk-road-8942329.html" data-href="http://www.independent.co.uk/news/uk/crime/teenager-patrick-mcmullen-who-died-while-on-skype-had-bought-drugs-from-silk-road-8942329.html" rel="nofollow">Patrick McMullen,</a> a
|
||||
17-year-old Scottish student, ingested half a gram of MDMA and three tabs
|
||||
of LSD, reportedly purchased from the Silk Road. While talking to his friends
|
||||
on Skype, his words became slurred and he passed out. Paramedics could
|
||||
not revive him. The coroner for that case, Sherrif Payne, who deemed the
|
||||
cause of death ecstasy toxicity, told <em>The Independent</em> “You
|
||||
never know the purity of what you are taking and you can easily come unstuck.”</p>
|
||||
<p id="5e9e" name="5e9e">ScreamMyName, a deep web user who has been active since the original Silk
|
||||
<p name="5e9e" id="5e9e">ScreamMyName, a deep web user who has been active since the original Silk
|
||||
Road, wants to alert users to the dangerous chemicals that are often mixed
|
||||
with drugs, and is using Energy Control as a means to do so.</p>
|
||||
<p id="19a6" name="19a6">“We’re at a time where some vendors are outright sending people poison.
|
||||
<p name="19a6" id="19a6">“We’re at a time where some vendors are outright sending people poison.
|
||||
Some do it unknowingly,” ScreamMyName told me in an encrypted message.
|
||||
“Cocaine production in South America is often tainted with either levamisole
|
||||
or phenacetine. Both poison to humans and both with severe side effects.”</p>
|
||||
<p id="9fef" name="9fef">In the case of Levamisole, those prescribing it are often not doctors
|
||||
<p name="9fef" id="9fef">In the case of Levamisole, those prescribing it are often not doctors
|
||||
but veterinarians, as Levamisole is commonly used on animals, primarily
|
||||
for the treatment of worms. If ingested by humans it can lead to cases
|
||||
of extreme eruptions of the skin, as <a data-href="http://www.ncbi.nlm.nih.gov/pubmed/22127712" href="http://www.ncbi.nlm.nih.gov/pubmed/22127712" rel="nofollow">documented in a study</a> from researchers at the University
|
||||
of extreme eruptions of the skin, as <a href="http://www.ncbi.nlm.nih.gov/pubmed/22127712" data-href="http://www.ncbi.nlm.nih.gov/pubmed/22127712" rel="nofollow">documented in a study</a> from researchers at the University
|
||||
of California, San Francisco. But Lladanosa has found Levamisole in cocaine
|
||||
samples; dealers use it to increase the product weight, allowing them to
|
||||
stretch their batch further for greater profit — and also, she says, because
|
||||
Levamisole has a strong stimulant effect.</p>
|
||||
<p id="7886" name="7886">“It got me sick as fuck,” Dr. Feel, an Evolution user, wrote on the site’s
|
||||
<p name="7886" id="7886">“It got me sick as fuck,” Dr. Feel, an Evolution user, wrote on the site’s
|
||||
forums after consuming cocaine that had been cut with 23 percent Levamisole,
|
||||
and later tested by Energy Control. “I was laid up in bed for several days
|
||||
because of that shit. The first night I did it, I thought I was going to
|
||||
die. I nearly drove myself to the ER.”</p>
|
||||
<p id="18d3" name="18d3">“More people die because of tainted drugs than the drugs themselves,”
|
||||
<p name="18d3" id="18d3">“More people die because of tainted drugs than the drugs themselves,”
|
||||
Dr. Feel added. “It’s the cuts and adulterants that are making people sick
|
||||
and killing them.”</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="552a" name="552a"><div>
|
||||
|
||||
<p><img data-height="1192" data-image-id="1*IWXhtSsVv0gNnCwnDEXk-Q.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*IWXhtSsVv0gNnCwnDEXk-Q.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="552a" id="552a">
|
||||
<div>
|
||||
<p id="839a" name="839a">The particular case of cocaine cut with Levamisole is one of the reasons
|
||||
|
||||
<p><img data-image-id="1*IWXhtSsVv0gNnCwnDEXk-Q.jpeg" data-width="2100" data-height="1192" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*IWXhtSsVv0gNnCwnDEXk-Q.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="839a" id="839a">The particular case of cocaine cut with Levamisole is one of the reasons
|
||||
that ScreamMyName has been pushing for more drug testing on the deep web
|
||||
markets. “I recognize that drug use isn’t exactly healthy, but why exacerbate
|
||||
the problem?” he told me when I contacted him after his post. “[Energy
|
||||
Control] provides a way for users to test the drugs they’ll use and for
|
||||
these very users to know what it is they’re putting in their bodies. Such
|
||||
services are in very short supply.”</p>
|
||||
<p id="18dc" name="18dc">After sending a number of Energy Control tests himself, ScreamMyName started
|
||||
<p name="18dc" id="18dc">After sending a number of Energy Control tests himself, ScreamMyName started
|
||||
a de facto crowd-sourcing campaign to get more drugs sent to the lab, and
|
||||
then shared the results, after throwing in some cash to get the ball rolling.
|
||||
<a data-href="https://blockchain.info/address/1Mi6VjMFqjcD48FPV7cnPB24MAtQQenRy3" href="https://blockchain.info/address/1Mi6VjMFqjcD48FPV7cnPB24MAtQQenRy3" rel="nofollow">He set up a Bitcoin wallet</a>, with the hope that users might chip in
|
||||
<a href="https://blockchain.info/address/1Mi6VjMFqjcD48FPV7cnPB24MAtQQenRy3" data-href="https://blockchain.info/address/1Mi6VjMFqjcD48FPV7cnPB24MAtQQenRy3" rel="nofollow">He set up a Bitcoin wallet</a>, with the hope that users might chip in
|
||||
to fund further tests. At the time of writing, the wallet has received
|
||||
a total of 1.81 bitcoins; around $430 at today’s exchange rates.</p>
|
||||
<p id="dcbd" name="dcbd">In posts to the Evolution community, ScreamMyName pitched this project
|
||||
<p name="dcbd" id="dcbd">In posts to the Evolution community, ScreamMyName pitched this project
|
||||
as something that will benefit users and keep drug dealer honest. “When
|
||||
the funds build up to a point where we can purchase an [Energy Control]
|
||||
test fee, we’ll do a US thread poll for a few days and try to cohesively
|
||||
decide on what vendor to test,” he continued.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="9d32" name="9d32"><div>
|
||||
|
||||
<p><img data-height="913" data-image-id="1*NGcrjfkV0l37iQH2uyYjEw.jpeg" data-width="1368" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*NGcrjfkV0l37iQH2uyYjEw.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="9d32" id="9d32">
|
||||
<div>
|
||||
<p id="bff6" name="bff6">Other members of the community have been helping out, too. PlutoPete,
|
||||
|
||||
<p><img data-image-id="1*NGcrjfkV0l37iQH2uyYjEw.jpeg" data-width="1368" data-height="913" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*NGcrjfkV0l37iQH2uyYjEw.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="bff6" id="bff6">Other members of the community have been helping out, too. PlutoPete,
|
||||
a vendor from the original Silk Road who sold cannabis seeds and other
|
||||
legal items, has provided ScreamMyName with packaging to safely send the
|
||||
samples to Barcelona. “A box of baggies, and a load of different moisture
|
||||
barrier bags,” PlutoPete told me over the phone. “That’s what all the vendors
|
||||
use.”</p>
|
||||
<p id="bb78" name="bb78">It’s a modest program so far. ScreamMyName told me that so far he had
|
||||
<p name="bb78" id="bb78">It’s a modest program so far. ScreamMyName told me that so far he had
|
||||
gotten enough public funding to purchase five different Energy Control
|
||||
tests, in addition to the ten or so he’s sent himself so far. “The program
|
||||
created is still in its infancy and it is growing and changing as we go
|
||||
along but I have a lot of faith in what we’re doing,” he says.</p>
|
||||
<p id="5638" name="5638">But the spirit is contagious: elmo666, the other deep web user testing
|
||||
<p name="5638" id="5638">But the spirit is contagious: elmo666, the other deep web user testing
|
||||
cocaine, originally kept the results of the drug tests to himself, but
|
||||
he, too, saw a benefit to distributing the data. “It is clear that it is
|
||||
a useful service to other users, keeping vendors honest and drugs (and
|
||||
|
@ -321,17 +369,17 @@
|
|||
on the forums, and then created a thread with summaries of the test results,
|
||||
as well as comments from the vendors if they provided it. Other users were
|
||||
soon basing their decisions on what to buy on elmo666‘s tests.</p>
|
||||
<p id="de75" name="de75">“I’m defo trying the cola based on the incredibly helpful elmo and his
|
||||
<p name="de75" id="de75">“I’m defo trying the cola based on the incredibly helpful elmo and his
|
||||
energy control results and recommendations,” wrote user jayk1984. On top
|
||||
of this, elmo666 plans to launch an independent site on the deep web that
|
||||
will collate all of these results, which should act as a resource for users
|
||||
of all the marketplaces.</p>
|
||||
<p id="6b72" name="6b72">As word of elmo666's efforts spread, he began getting requests from drug
|
||||
<p name="6b72" id="6b72">As word of elmo666's efforts spread, he began getting requests from drug
|
||||
dealers who wanted him to use their wares for testing. Clearly, they figured
|
||||
that a positive result from Energy Control would be a fantastic marketing
|
||||
tool to draw more customers. They even offered elmo666 free samples. (He
|
||||
passed.)</p>
|
||||
<p id="b008" name="b008">Meanwhile, some in the purchasing community are arguing that those running
|
||||
<p name="b008" id="b008">Meanwhile, some in the purchasing community are arguing that those running
|
||||
markets on the deep web should be providing quality control themselves.
|
||||
PlutoPete told me over the phone that he had been in discussions about
|
||||
this with Dread Pirate Roberts, the pseudonymous owner of the original
|
||||
|
@ -339,7 +387,7 @@
|
|||
on Silk Road 1, doing lots of anonymous buys to police each category. But
|
||||
of course they took the thing [Silk Road] down before we got it properly
|
||||
off the ground,” he lamented.</p>
|
||||
<p id="49c8" name="49c8">But perhaps it is best that the users, those who are actually consuming
|
||||
<p name="49c8" id="49c8">But perhaps it is best that the users, those who are actually consuming
|
||||
the drugs, remain in charge of shaming dealers and warning each other.
|
||||
“It’s our responsibility to police the market based on reviews and feedback,”
|
||||
elmo666 wrote in an Evolution forum post. It seems that in the lawless
|
||||
|
@ -347,35 +395,40 @@
|
|||
sold openly, users have cooperated in an organic display of self-regulation
|
||||
to stamp out those particular batches of drugs that are more likely to
|
||||
harm users.</p>
|
||||
<p id="386d" name="386d">“That’s always been the case with the deep web,” PlutoPete told me. Indeed,
|
||||
<p name="386d" id="386d">“That’s always been the case with the deep web,” PlutoPete told me. Indeed,
|
||||
ever since Silk Road, a stable of the drug markets has been the review
|
||||
system, where buyers can leave a rating and feedback for vendors, letting
|
||||
others know about the reliability of the seller. But DoctorX’s lab, rigorously
|
||||
testing the products with scientific instruments, takes it a step further.</p>
|
||||
</div>
|
||||
<div>
|
||||
<figure id="890b" name="890b"><div>
|
||||
|
||||
<p><img data-height="1373" data-image-id="1*WRlKt3q3mt7utmwxcbl3sQ.jpeg" data-width="2100" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*WRlKt3q3mt7utmwxcbl3sQ.jpeg"></img></p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption></figure></div>
|
||||
<figure name="890b" id="890b">
|
||||
<div>
|
||||
<p id="b109" name="b109">“In the white market, they have quality control. In the dark market, it
|
||||
|
||||
<p><img data-image-id="1*WRlKt3q3mt7utmwxcbl3sQ.jpeg" data-width="2100" data-height="1373" src="https://d262ilb51hltx0.cloudfront.net/max/2000/1*WRlKt3q3mt7utmwxcbl3sQ.jpeg">
|
||||
</p></div>
|
||||
<figcaption>Photo by Joan Bardeletti</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div>
|
||||
<p name="b109" id="b109">“In the white market, they have quality control. In the dark market, it
|
||||
should be the same,” Cristina Gil Lladanosa says to me before I leave the
|
||||
Barcelona lab.</p>
|
||||
<p id="e3a4" name="e3a4">A week after I visit the lab, the results of the MDMA arrive in my inbox:
|
||||
<p name="e3a4" id="e3a4">A week after I visit the lab, the results of the MDMA arrive in my inbox:
|
||||
it is 85 percent pure, with no indications of other active ingredients.
|
||||
Whoever ordered that sample from the digital shelves of the deep web, and
|
||||
had it shipped to their doorstep in Canada, got hold of some seriously
|
||||
good, and relatively safe drugs. And now they know it.</p>
|
||||
<figure id="31cf" name="31cf"><div>
|
||||
<figure name="31cf" id="31cf">
|
||||
<div>
|
||||
|
||||
<p><img data-action="zoom" data-action-value="1*320_4I0lxbn5x3bx4XPI5Q.png" data-height="24" data-image-id="1*320_4I0lxbn5x3bx4XPI5Q.png" data-width="1200" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*320_4I0lxbn5x3bx4XPI5Q.png"></img></p></div>
|
||||
</figure><p data-align="center" id="9b87" name="9b87"><em>Top photo by Joan Bardeletti</em>
|
||||
<p><img data-image-id="1*320_4I0lxbn5x3bx4XPI5Q.png" data-width="1200" data-height="24" data-action="zoom" data-action-value="1*320_4I0lxbn5x3bx4XPI5Q.png" src="https://d262ilb51hltx0.cloudfront.net/max/800/1*320_4I0lxbn5x3bx4XPI5Q.png">
|
||||
</p></div>
|
||||
</figure>
|
||||
<p name="9b87" id="9b87" data-align="center"><em>Top photo by Joan Bardeletti</em>
|
||||
</p>
|
||||
<p data-align="center" id="c30a" name="c30a">Follow Backchannel: <a data-href="https://twitter.com/backchnnl" href="https://twitter.com/backchnnl" rel="nofollow"><em>Twitter</em></a>
|
||||
<em>|</em><a data-href="https://www.facebook.com/pages/Backchannel/1488568504730671" href="https://www.facebook.com/pages/Backchannel/1488568504730671" rel="nofollow"><em>Facebook</em></a>
|
||||
<p name="c30a" id="c30a" data-align="center">Follow Backchannel: <a href="https://twitter.com/backchnnl" data-href="https://twitter.com/backchnnl" rel="nofollow"><em>Twitter</em></a>
|
||||
<em>|</em><a href="https://www.facebook.com/pages/Backchannel/1488568504730671" data-href="https://www.facebook.com/pages/Backchannel/1488568504730671" rel="nofollow"><em>Facebook</em></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section></div>
|
||||
</div>
|
|
@ -1,9 +1,12 @@
|
|||
<article data-asociarposwall="false" data-login="false" data-loginposwall="false" id="nota" itemscope="" itemtype="http://schema.org/NewsArticle"><div>
|
||||
<article id="nota" itemscope itemtype="http://schema.org/NewsArticle" data-login="false" data-loginposwall="false" data-asociarposwall="false">
|
||||
<div>
|
||||
<p itemprop="description">Los pueblos indígenas reclaman por derechos que permanecen
|
||||
incumplidos, por eso es más eficiente canalizar la protesta que reprimirla</p>
|
||||
</div>
|
||||
<section id="cuerpo" itemprop="articleBody">
|
||||
|
||||
|
||||
|
||||
<p>Abdullah Ocalan, el líder independentista kurdo, desembarcó en Italia en noviembre de
|
||||
1998 y pidió asilo político. Arrastraba un pedido de captura de Turquía, donde era acusado por
|
||||
terrorismo. El ex comunista Massimo D'Alema, recién asumido, dudaba. Acoger a Ocalan implicaba comprarse
|
||||
|
@ -21,8 +24,12 @@
|
|||
supuestos contactos internacionales de organizaciones mapuches. Entre ellos aparecía Ocalan, a quien el
|
||||
informe ubicó "con domicilios en Palermo y en el centro porteño", y aseguraba incluso que había sido
|
||||
visto "en Neuquén, Río Negro y Chubut durante el juicio a Jones Huala".</p>
|
||||
<figure><p><span title="Ampliar imagen"></span><img src="http://bucket2.glanacion.com/anexos/fotos/77/conflicto-mapuche-2585177w280.jpg"></img></p>
|
||||
<figcaption id="epigrafe2585177">Foto: LA NACION</figcaption></figure><p>Esta falsa noticia fue la más rocambolesca de una larga cadena. Dos hechos quedaron en evidencia:
|
||||
<figure>
|
||||
<p><span title="Ampliar imagen"></span><img src="http://bucket2.glanacion.com/anexos/fotos/77/conflicto-mapuche-2585177w280.jpg"></p>
|
||||
<figcaption id="epigrafe2585177">Foto: LA NACION</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Esta falsa noticia fue la más rocambolesca de una larga cadena. Dos hechos quedaron en evidencia:
|
||||
primero, que hay periodistas que no chequean la información; segundo, que los servicios de inteligencia
|
||||
los utilizan para manipular la agenda pública. Y sobre los servicios hay dos posibilidades: o son burros
|
||||
o son perversos. Las opciones no son excluyentes, aunque cualquiera alcanza para tornarlos indignos de
|
||||
|
@ -37,6 +44,7 @@
|
|||
Estado", vincular a un grupo que reclama tierras en la región de sus ancestros con otro que busca
|
||||
gobernar el mundo según sus normas religiosas y ha masacrado a miles de personas requiere de una
|
||||
operación intelectual tan audaz como inadecuada.</p>
|
||||
|
||||
<p>La asociación con el movimiento kurdo, en cambio, asoma menos inverosímil. Desde su arresto, Ocalan
|
||||
transformó su pensamiento: de una visión nacionalista con inspiración estalinista evolucionó al
|
||||
confederalismo democrático, una propuesta de organización comunal, ecologista, más apegada a las raíces
|
||||
|
@ -54,6 +62,7 @@
|
|||
matar directamente, es realizar sabotajes, movilizaciones, ataques a iglesias y empresas y mucha
|
||||
prensa". ¡En Medio Oriente pagarían por un terrorismo así! Ningún hecho de violencia debe ser
|
||||
minimizado, pero las analogías no resisten prueba.</p>
|
||||
|
||||
<p>La "cuestión mapuche" es social antes que policial. La Constitución manda "reconocer la preexistencia
|
||||
étnica y cultural de los pueblos indígenas argentinos. Garantizar el respeto a su identidad?; reconocer
|
||||
la personería jurídica de sus comunidades, y la posesión y propiedad comunitarias de las tierras que
|
||||
|
@ -82,4 +91,6 @@
|
|||
del Estado argentino no fue tanto quiénes lo desafiaron como quiénes lo gobernaron. Cambiemos.</p>
|
||||
<p><b><i>Andrés Malamud es politólogo e investigador en la Universidad de Lisboa. Martín Schapiro es abogado
|
||||
administrativista y analista internacional</i></b></p>
|
||||
</section></article>
|
||||
|
||||
</section>
|
||||
</article>
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Author": null,
|
||||
"Author": "Martin Untersinger (avec Damien Leloup et Morgane Tual)",
|
||||
"Direction": null,
|
||||
"Excerpt": "Largement approuvé par les députés, le texte sera désormais examiné par le Sénat, puis le Conseil constitutionnel.",
|
||||
"Image": "http:\/\/s1.lemde.fr\/image\/2015\/05\/05\/600x315\/4628128_3_47fc_projet-de-loi-renseignement_aeba800424730d672d1bd08faf203438.jpg",
|
||||
|
|
|
@ -1,38 +1,33 @@
|
|||
<p> <span data-source="Le Monde.fr" id="publisher" itemprop="Publisher">Le Monde</span> |
|
||||
<time datetime="2015-05-04T13:36:31+02:00" itemprop="datePublished">04.05.2015 à 13h36</time> • Mis à jour le
|
||||
<time datetime="2015-05-05T20:13:12+02:00" itemprop="dateModified">05.05.2015 à 20h13</time> | <span>
|
||||
Par <span itemprop="author"> <a href="http://fakehost/journaliste/martin-untersinger/" target="_blank">Martin Untersinger</a> (avec Damien Leloup et Morgane Tual)
|
||||
</span> </span>
|
||||
</p><div id="articleBody" itemprop="articleBody">
|
||||
<div id="articleBody" itemprop="articleBody">
|
||||
<p>
|
||||
<iframe frameborder="0" height="320" src="//www.dailymotion.com/embed/video/x2p552m?syndication=131181" width="534"></iframe>
|
||||
<iframe src="//www.dailymotion.com/embed/video/x2p552m?syndication=131181" frameborder="0" width="534" height="320"></iframe>
|
||||
</p>
|
||||
<p>Les députés ont, sans surprise, adopté à une large majorité (438 contre 86 et 42 abstentions) le projet de loi sur le renseignement défendu par le gouvernement lors d’un vote solennel, mardi 5 mai. Il sera désormais examiné par le Sénat, puis le Conseil constitutionnel, prochainement saisi par 75 députés. Dans un souci d'apaisement, François Hollande avait annoncé par avance qu'il saisirait les Sages.</p>
|
||||
<p>Les députés ont, sans surprise, adopté à une large majorité (438 contre 86 et 42 abstentions) le projet de loi sur le renseignement défendu par le gouvernement lors d’un vote solennel, mardi 5 mai. Il sera désormais examiné par le Sénat, puis le Conseil constitutionnel, prochainement saisi par 75 députés. Dans un souci d'apaisement, François Hollande avait annoncé par avance qu'il saisirait les Sages.</p>
|
||||
<p><strong>Revivez <a href="http://fakehost/pixels/live/2015/05/05/suivez-le-vote-de-la-loi-renseignement-en-direct_4628012_4408996.html">le direct du vote à l’Assemblée avec vos questions.</a></strong></p>
|
||||
<p>Ont voté contre : 10 députés socialistes (sur 288), 35 UMP (sur 198), 11 écologistes (sur 18), 11 UDI (sur 30), 12 députés Front de gauche (sur 15) et 7 non-inscrits (sur 9). <a href="http://www2.assemblee-nationale.fr/scrutins/detail/%28legislature%29/14/%28num%29/1109">Le détail est disponible sur le site de l'Assemblée nationale.</a></p>
|
||||
<p>Parmi les députés ayan voté contre figurent notamment des opposants de la première heure, comme l'UMP Laure de la Raudière ou l'écologiste Sergio Coronado, mais aussi quelques poids lourds de l'opposition comme Patrick Devedjian ou Claude Goasguen. A gauche, on trouve parmi les quelque opposants au texte Aurélie Filipetti. Christian Paul, qui avait été très actif lors d'autres débats sur les libertés numériques, s'est abstenu.</p>
|
||||
<p>Pouria Amirshahi, député socialiste des Français de l'étranger qui a également voté contre, a annoncé qu'il transmettrait un « mémorandum argumenté » au Conseil constitutionnel et demanderait à se faire auditionner sur le projet de loi. D'autres députés ont prévu de faire la même démarche.</p>
|
||||
<p>Pouria Amirshahi, député socialiste des Français de l'étranger qui a également voté contre, a annoncé qu'il transmettrait un « mémorandum argumenté » au Conseil constitutionnel et demanderait à se faire auditionner sur le projet de loi. D'autres députés ont prévu de faire la même démarche.</p>
|
||||
<p>Ce texte, fortement décrié par la société civile pour son manque de contre-pouvoir et le caractère intrusif des techniques qu’il autorise, entend donner un cadre aux pratiques des services de renseignement, rendant légales certaines pratiques qui, jusqu’à présent, ne l’étaient pas.</p>
|
||||
<p><u>Retour sur ses principales dispositions, après son passage en commission des lois et après le débat en séance publique.</u></p>
|
||||
<h2>Définition des objectifs des services</h2>
|
||||
<p>Le projet de loi énonce les domaines que peuvent invoquer les services pour justifier leur surveillance. Il s’agit notamment, de manière attendue, de <em>« l’indépendance nationale, de l’intégrité du territoire et de la défense nationale »</em> et de<em> « la prévention du terrorisme »,</em> mais également des <em>« intérêts majeurs de la politique étrangère »,</em> ainsi que de la <em>« prévention des atteintes à la forme républicaine des institutions »</em> et de <em>« la criminalité et de la délinquance organisées »</em>. Des formulations parfois larges qui inquiètent les opposants au texte qui craignent qu’elles puissent permettre de surveiller des activistes ou des manifestants.</p>
|
||||
<p>Le projet de loi énonce les domaines que peuvent invoquer les services pour justifier leur surveillance. Il s’agit notamment, de manière attendue, de <em>« l’indépendance nationale, de l’intégrité du territoire et de la défense nationale »</em> et de<em> « la prévention du terrorisme »,</em> mais également des <em>« intérêts majeurs de la politique étrangère »,</em> ainsi que de la <em>« prévention des atteintes à la forme républicaine des institutions »</em> et de <em>« la criminalité et de la délinquance organisées »</em>. Des formulations parfois larges qui inquiètent les opposants au texte qui craignent qu’elles puissent permettre de surveiller des activistes ou des manifestants.</p>
|
||||
<h2>La Commission de contrôle</h2>
|
||||
<p>Le contrôle de cette surveillance sera confié à une nouvelle autorité administrative indépendante, la Commission nationale de contrôle des techniques de renseignement (CNCTR), composée de six magistrats du Conseil d’Etat et de la Cour de cassation, de trois députés et trois sénateurs de la majorité et de l’opposition, et d’un expert technique. Elle remplacera l’actuelle Commission nationale de contrôle des interceptions de sécurité (CNCIS).</p>
|
||||
<p>Elle délivrera son avis, sauf cas d’urgence, avant toute opération de surveillance ciblée. Deux types urgences sont prévus par la loi : d’un côté une <em>« urgence absolue »</em>, pour laquelle un agent pourra se passer de l’avis de la CNCTR mais pas de l’autorisation du premier ministre. De l’autre, une urgence opérationnelle extrêmement limitée, notamment en termes de techniques, à l’initiative du chef du service de renseignement, qui se passe de l’avis de la CNCTR. Ces cas d’urgence ne justifieront pas l’intrusion d’un domicile ni la surveillance d’un journaliste, un parlementaire ou un avocat. Dans ces cas, la procédure classique devra s’appliquer.</p>
|
||||
<p>Elle délivrera son avis, sauf cas d’urgence, avant toute opération de surveillance ciblée. Deux types urgences sont prévus par la loi : d’un côté une <em>« urgence absolue »</em>, pour laquelle un agent pourra se passer de l’avis de la CNCTR mais pas de l’autorisation du premier ministre. De l’autre, une urgence opérationnelle extrêmement limitée, notamment en termes de techniques, à l’initiative du chef du service de renseignement, qui se passe de l’avis de la CNCTR. Ces cas d’urgence ne justifieront pas l’intrusion d’un domicile ni la surveillance d’un journaliste, un parlementaire ou un avocat. Dans ces cas, la procédure classique devra s’appliquer.</p>
|
||||
<p>L’avis de la CNCTR ne sera pas contraignant, mais cette commission pourra saisir le Conseil d’Etat si elle estime que la loi n’est pas respectée et elle disposera de pouvoirs d’enquête. Ce recours juridictionnel est une nouveauté dans le monde du renseignement.</p>
|
||||
<h2>Les « boîtes noires »</h2>
|
||||
<p>Une des dispositions les plus contestées de ce projet de loi prévoit de pouvoir contraindre les fournisseurs d’accès à Internet (FAI) à « <em>détecter une menace terroriste sur la base d’un traitement automatisé ». </em>Ce dispositif – autorisé par le premier ministre par tranche de quatre mois – permettrait de détecter, en temps réel ou quasi réel, les personnes ayant une activité en ligne typique de « schémas » utilisés par les terroristes pour transmettre des informations.</p>
|
||||
<p>En pratique, les services de renseignement pourraient installer chez les FAI une « boîte noire » surveillant le trafic. Le contenu des communications – qui resterait « anonyme » – ne serait pas surveillé, mais uniquement les métadonnées : origine ou destinataire d’un message, adresse IP d’un site visité, durée de la conversation ou de la connexion… Ces données ne seraient pas conservées.</p>
|
||||
<h2>Les « boîtes noires »</h2>
|
||||
<p>Une des dispositions les plus contestées de ce projet de loi prévoit de pouvoir contraindre les fournisseurs d’accès à Internet (FAI) à « <em>détecter une menace terroriste sur la base d’un traitement automatisé ». </em>Ce dispositif – autorisé par le premier ministre par tranche de quatre mois – permettrait de détecter, en temps réel ou quasi réel, les personnes ayant une activité en ligne typique de « schémas » utilisés par les terroristes pour transmettre des informations.</p>
|
||||
<p>En pratique, les services de renseignement pourraient installer chez les FAI une « boîte noire » surveillant le trafic. Le contenu des communications – qui resterait « anonyme » – ne serait pas surveillé, mais uniquement les métadonnées : origine ou destinataire d’un message, adresse IP d’un site visité, durée de la conversation ou de la connexion… Ces données ne seraient pas conservées.</p>
|
||||
<p>La Commission nationale informatique et libertés<strong> </strong>(CNIL), qui critique fortement cette disposition. La CNIL soulève notamment que l’anonymat de ces données est très relatif, puisqu’il peut être levé.</p>
|
||||
<p>Lire aussi : <a href="http://fakehost/pixels/article/2015/03/18/les-critiques-de-la-cnil-contre-le-projet-de-loi-sur-le-renseignement_4595839_4408996.html">Les critiques de la CNIL contre le projet de loi sur le renseignement</a> </p>
|
||||
<p>Le dispositif introduit une forme de « pêche au chalut » – un brassage très large des données des Français à la recherche de quelques individus. Le gouvernement se défend de toute similarité avec les dispositifs mis en place par la NSA américaine, arguant notamment que les données ne seront pas conservées et que cette activité sera contrôlée par une toute nouvelle commission aux moyens largement renforcés. Il s’agit cependant d’un dispositif très large, puisqu’il concernera tous les fournisseurs d’accès à Internet, et donc tous les internautes français.</p>
|
||||
<h2>L’élargissement de la surveillance électronique pour détecter les « futurs » terroristes</h2>
|
||||
<p>La surveillance des métadonnées sera aussi utilisée pour tenter de détecter de nouveaux profils de terroristes potentiels, prévoit le projet de loi. Le gouvernement considère qu’il s’agit d’une manière efficace de détecter les profils qui passent aujourd’hui <em>« entre les mailles du filet »</em>, par exemple des personnes parties en Syrie ou en Irak sans qu’aucune activité suspecte n’ait été décelée avant leur départ.</p>
|
||||
<p>Lire aussi : <a href="http://fakehost/pixels/article/2015/03/18/les-critiques-de-la-cnil-contre-le-projet-de-loi-sur-le-renseignement_4595839_4408996.html">Les critiques de la CNIL contre le projet de loi sur le renseignement</a> </p>
|
||||
<p>Le dispositif introduit une forme de « pêche au chalut » – un brassage très large des données des Français à la recherche de quelques individus. Le gouvernement se défend de toute similarité avec les dispositifs mis en place par la NSA américaine, arguant notamment que les données ne seront pas conservées et que cette activité sera contrôlée par une toute nouvelle commission aux moyens largement renforcés. Il s’agit cependant d’un dispositif très large, puisqu’il concernera tous les fournisseurs d’accès à Internet, et donc tous les internautes français.</p>
|
||||
<h2>L’élargissement de la surveillance électronique pour détecter les « futurs » terroristes</h2>
|
||||
<p>La surveillance des métadonnées sera aussi utilisée pour tenter de détecter de nouveaux profils de terroristes potentiels, prévoit le projet de loi. Le gouvernement considère qu’il s’agit d’une manière efficace de détecter les profils qui passent aujourd’hui <em>« entre les mailles du filet »</em>, par exemple des personnes parties en Syrie ou en Irak sans qu’aucune activité suspecte n’ait été décelée avant leur départ.</p>
|
||||
<p>Pour repérer ces personnes, la loi permettra d’étendre la surveillance électronique à toutes les personnes en contact avec des personnes déjà suspectées. En analysant leurs contacts, la fréquence de ces derniers et les modes de communication, les services de renseignement espèrent pouvoir détecter ces nouveaux profils en amont.</p>
|
||||
<h2>De nouveaux outils et méthodes de collecte</h2>
|
||||
<p>Les services pourront également procéder, après un avis de la CNCTR, à la pose de micros dans une pièce ou de mouchards sur un objet (voiture par exemple), ou à l’intérieur d’un ordinateur. L’utilisation des IMSI-catchers (fausses antennes qui permettent d’intercepter des conversations téléphoniques) est également légalisée, pour les services de renseignement, dans certains cas. Le nombre maximal de ces appareils sera fixé par arrêté du premier ministre après l’avis de la CNCTR.</p>
|
||||
<p><strong>Lire : <a href="http://fakehost/pixels/article/2015/03/31/que-sont-les-imsi-catchers-ces-valises-qui-espionnent-les-telephones-portables_4605827_4408996.html">Que sont les IMSI-catchers, ces valises qui espionnent les téléphones portables ?</a></strong></p>
|
||||
<p>La loi introduit également des mesures de surveillance internationale : concrètement, les procédures de contrôle seront allégées lorsqu’un des « bouts » de la communication sera situé à l’étranger (concrètement, un Français qui parle avec un individu situé à l’étranger). Cependant, comme l’a souligné l’Arcep (l’Autorité de régulation des communications électroniques et des postes), sollicitée pour le versant technique de cette mesure, il est parfois difficile de s’assurer qu’une communication, même passant par l’étranger, ne concerne pas deux Français.</p>
|
||||
<p><strong>Lire : <a href="http://fakehost/pixels/article/2015/03/31/que-sont-les-imsi-catchers-ces-valises-qui-espionnent-les-telephones-portables_4605827_4408996.html">Que sont les IMSI-catchers, ces valises qui espionnent les téléphones portables ?</a></strong></p>
|
||||
<p>La loi introduit également des mesures de surveillance internationale : concrètement, les procédures de contrôle seront allégées lorsqu’un des « bouts » de la communication sera situé à l’étranger (concrètement, un Français qui parle avec un individu situé à l’étranger). Cependant, comme l’a souligné l’Arcep (l’Autorité de régulation des communications électroniques et des postes), sollicitée pour le versant technique de cette mesure, il est parfois difficile de s’assurer qu’une communication, même passant par l’étranger, ne concerne pas deux Français.</p>
|
||||
<h2>Un nouveau fichier</h2>
|
||||
<p>La loi crée un fichier judiciaire national automatisé des auteurs d’infractions terroristes (Fijait), dont les données pourront être conservées pendant vingt ans.</p>
|
||||
<p>Ce fichier concerne les personnes ayant été condamnées, même si une procédure d’appel est en cours. Les mineurs pourront aussi être inscrits dans ce fichier et leurs données conservées jusqu’à dix ans. L’inscription ne sera pas automatique et se fera sur décision judiciaire. Certaines mises en examen pourront aussi apparaître sur ce fichier. En cas de non-lieu, relaxe, acquittement, amnistie ou réhabilitation, ces informations seront effacées.</p>
|
||||
|
@ -40,7 +35,7 @@ Par <span itemprop="author"> <a href="http://fakehost/journalist
|
|||
<p>Le renseignement pénitentiaire pourra, dans des conditions qui seront fixées par décret, profiter des techniques que légalise le projet de loi pour les services de renseignement. La ministre de la justice, Christiane Taubira, était défavorable à cette disposition, soutenue par le rapporteur du texte, la droite et une partie des députés de gauche. Pour la ministre, cette innovation va dénaturer le renseignement pénitentiaire et le transformer en véritable service de renseignement.</p>
|
||||
<h2>Conservation des données</h2>
|
||||
<p>La CNIL <a href="http://www.cnil.fr/fileadmin/documents/La_CNIL/actualite/Les_propositions_de_la_CNIL_sur_les_evolutions_de_la_loi_Informatique_et_Libertes.pdf">a fait part à plusieurs reprises de sa volonté</a> d’exercer sa mission de contrôle sur les fichiers liés au renseignement, qui seront alimentés par ces collectes. Ces fichiers sont aujourd’hui exclus du périmètre d’action de la CNIL.</p>
|
||||
<p>La durée de conservation des données collectées – et l’adaptation de cette durée à la technique employée – a par ailleurs été inscrite dans la loi, contrairement au projet initial du gouvernement qui entendait fixer ces limites par décret. Elle pourra aller jusqu’à cinq ans dans le cas des données de connexion.</p>
|
||||
<p>La durée de conservation des données collectées – et l’adaptation de cette durée à la technique employée – a par ailleurs été inscrite dans la loi, contrairement au projet initial du gouvernement qui entendait fixer ces limites par décret. Elle pourra aller jusqu’à cinq ans dans le cas des données de connexion.</p>
|
||||
<h2>Un dispositif pour les lanceurs d’alerte</h2>
|
||||
<p>La loi prévoit également une forme de protection pour les agents qui seraient témoins de surveillance illégale. Ces lanceurs d’alerte pourraient solliciter la CNCTR, voire le premier ministre, et leur fournir toutes les pièces utiles. La CNCTR pourra ensuite aviser le procureur de la République et solliciter la Commission consultative du secret de la défense nationale afin que cette dernière <em>« donne au premier ministre son avis sur la possibilité de déclassifier tout ou partie de ces éléments »</em>. Aucune mesure de rétorsion ne pourra viser l’agent qui aurait dénoncé des actes potentiellement illégaux.</p>
|
||||
<p>La loi prévoit également une forme de protection pour les agents qui seraient témoins de surveillance illégale. Ces lanceurs d’alerte pourraient solliciter la CNCTR, voire le premier ministre, et leur fournir toutes les pièces utiles. La CNCTR pourra ensuite aviser le procureur de la République et solliciter la Commission consultative du secret de la défense nationale afin que cette dernière <em>« donne au premier ministre son avis sur la possibilité de déclassifier tout ou partie de ces éléments »</em>. Aucune mesure de rétorsion ne pourra viser l’agent qui aurait dénoncé des actes potentiellement illégaux.</p>
|
||||
</div>
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"Author": null,
|
||||
"Author": "Collectif",
|
||||
"Direction": null,
|
||||
"Excerpt": "Le retour à la stabilité coûtera des milliards d'euros, mais l'Union européenne en vaut la peine, estime un collectif d'industriels.",
|
||||
"Excerpt": "Le retour \u00e0 la stabilit\u00e9 co\u00fbtera des milliards d'euros, mais l'Union europ\u00e9enne en vaut la peine, estime un collectif d'industriels.",
|
||||
"Image": "http:\/\/s1.lemde.fr\/medias\/web\/1.2.705\/img\/placeholder\/default.png",
|
||||
"Title": "La crise européenne est une crise de la dette, pas de l'euro",
|
||||
"SiteName": "Le Monde.fr"
|
||||
"Title": "La crise europ\u00e9enne est une crise de la dette, pas de l'euro",
|
||||
"SiteName": "Le Monde"
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue