mediawiki-extensions-Secure.../includes/ListFetcher.php
Reedy 2e20b3edcd Fetch list from GitHub
For some reason Mozilla is blocking our requests from Toolforge,
using GitHub is something we know that works and should be the
same in practice.

Bug: T292242
Change-Id: Ic7d5da9758122ecb36f5e8f43716b4f8cf6f889d
2021-11-24 21:56:13 +00:00

126 lines
3.6 KiB
PHP

<?php
/**
* Copyright (C) 2018-2019 Kunal Mehta <legoktm@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace MediaWiki\SecureLinkFixer;
use DateTime;
use RuntimeException;
use Wikimedia\StaticArrayWriter;
/**
* Downloads Mozilla's HSTS preload list and builds it into a PHP file.
*
* We explicitly don't use any MediaWiki code so that this class
* can be run without needing all of MediaWiki to be installed. The
* only exception right now is the StaticArrayWriter class.
*/
class ListFetcher {
/** @var ?callable */
private $output;
private const HTTP_OPTIONS = [
'http' => [ 'method' => 'GET', 'header' => [ 'User-Agent: MediaWiki SecureLinkFixer' ] ]
];
/**
* @param callable|null $output
*/
public function __construct( callable $output = null ) {
$this->output = $output;
}
/**
* @param string $text
*/
private function output( $text ) {
if ( $this->output ) {
call_user_func( $this->output, $text );
}
}
/**
* Fetches the latest revision/date available from GitHub mozilla/gecko-dev
*
* @return string[]
*/
public function getLatestInfo(): array {
// phpcs:ignore Generic.Files.LineLength
$changesUrl = 'https://api.github.com/repos/mozilla/gecko-dev/commits?sha=master&per_page=1&path=security%2Fmanager%2Fssl%2FnsSTSPreloadList.inc';
$json = json_decode(
file_get_contents(
$changesUrl,
false,
stream_context_create( self::HTTP_OPTIONS )
)
);
if ( !isset( $json[0]->sha ) ) {
throw new RuntimeException( "Unable to parse revision id/updated date for HSTS preload list" );
}
$rev = $json[0]->sha;
$date = new DateTime( $json[0]->commit->author->date );
return [ $rev, $date->format( 'Y-m-d' ) ];
}
/**
* Downloads the list for the given revision/date and formats it for PHP
*
* @param string $rev git revision
* @param string $date YYYY-MM-DD formatted date
* @return string PHP file code
*/
public function fetchList( $rev, $date ) {
$this->output( "Downloading the HSTS preload list (revision $rev)..." );
// phpcs:ignore Generic.Files.LineLength
$url = "https://github.com/mozilla/gecko-dev/raw/$rev/security/manager/ssl/nsSTSPreloadList.inc";
$lines = explode( "\n",
file_get_contents(
$url,
false,
stream_context_create( self::HTTP_OPTIONS )
)
);
$this->output( "done\n" );
$inList = false;
$header = <<<HEADER
Generated by fetchList.php using mozilla/gecko-dev@$rev ($date)
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
phpcs:ignoreFile
HEADER;
// XXX: Should we care about gPreloadListExpirationTime?
$data = [];
foreach ( $lines as $line ) {
if ( $line === '%%' ) {
$inList = !$inList;
continue;
}
if ( $inList ) {
$exploded = explode( ', ', $line );
$data[$exploded[0]] = (int)$exploded[1];
}
}
$writer = new StaticArrayWriter();
return $writer->create( $data, $header );
}
}