diff --git a/composer.json b/composer.json index 599cb6c8..b22aaca8 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,9 @@ "phpunit/phpunit": "9.6.34", "mediawiki/mediawiki-codesniffer": "48.0.0", "mustangostang/spyc": "0.6.3", - "mhujer/yaml-sort-checker": "^1.5" + "mhujer/yaml-sort-checker": "^1.5", + "symfony/console": "^5.4", + "psr/log": "^2.0" }, "support": { diff --git a/composer.lock b/composer.lock index a15fc899..e9663462 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "85f1c270bb3aa7ad6e52f1c4c1c11c5c", + "content-hash": "00de89cd3f7bab314cb7a918fef32994", "packages": [], "packages-dev": [ { @@ -1393,6 +1393,56 @@ }, "time": "2021-11-05T16:47:00+00:00" }, + { + "name": "psr/log", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/ef29f6d262798707a9edd554e2b82517ef3a9376", + "reference": "ef29f6d262798707a9edd554e2b82517ef3a9376", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/2.0.0" + }, + "time": "2021-07-14T16:41:46+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.2", diff --git a/src/LanguageUtil.php b/src/LanguageUtil.php index 7468ba3f..2dfc6546 100644 --- a/src/LanguageUtil.php +++ b/src/LanguageUtil.php @@ -50,7 +50,12 @@ public static function get(): LanguageUtil { } private function loadData() { - $this->data = json_decode( file_get_contents( __DIR__ . '/' . self::LANGUAGE_DATA_PATH ) ); + $path = realpath( __DIR__ . '/' . self::LANGUAGE_DATA_PATH ); + if ( $path && str_starts_with( $path, dirname( __DIR__ ) ) ) { + $this->data = json_decode( file_get_contents( $path ) ); + } else { + throw new \RuntimeException( 'Invalid language data file path' ); + } } /** diff --git a/src/util/ulsdata2json.php b/src/util/ulsdata2json.php index a2595507..cae0d4f9 100644 --- a/src/util/ulsdata2json.php +++ b/src/util/ulsdata2json.php @@ -12,12 +12,24 @@ * @license GPL-2.0-or-later */ -require_once __DIR__ . '/../../vendor/autoload.php'; +use Symfony\Component\Console\Logger\ConsoleLogger; +use Symfony\Component\Console\Output\ConsoleOutput; + +$safeFile = __DIR__ . '/../../vendor/autoload.php'; +require_once $safeFile; + +$output = new ConsoleOutput(); +$logger = new ConsoleLogger( $output ); define( 'DATA_DIRECTORY', __DIR__ . '/../../data' ); -print "Reading langdb.yaml...\n"; -$yamlLangdb = file_get_contents( DATA_DIRECTORY . '/langdb.yaml' ); +$logger->info( "Reading langdb.yaml..." ); +$langdbPath = realpath( DATA_DIRECTORY . '/langdb.yaml' ); +if ( $langdbPath && is_readable( $langdbPath ) ) { + $yamlLangdb = file_get_contents( $langdbPath ); +} else { + throw new Exception( "Cannot read langdb.yaml" ); +} $parsedLangdb = spyc_load( $yamlLangdb ); $supplementalDataFilename = 'supplementalData.xml'; @@ -27,27 +39,32 @@ $curl = curl_init( $supplementalDataUrl ); $supplementalDataFile = fopen( $supplementalDataFilename, 'w' ); +if ( !$supplementalDataFile ) { + throw new Exception( "Cannot open file for writing" ); +} curl_setopt( $curl, CURLOPT_FILE, $supplementalDataFile ); curl_setopt( $curl, CURLOPT_HEADER, 0 ); -print "Trying to download $supplementalDataUrl...\n"; +$logger->info( "Trying to download $supplementalDataUrl..." ); $curlSuccess = curl_exec( $curl ); curl_close( $curl ); fclose( $supplementalDataFile ); if ( !$curlSuccess ) { - die( "Failed to download CLDR data from $supplementalDataUrl.\n" ); + $logger->error( "Failed to download CLDR data from $supplementalDataUrl." ); + exit( 1 ); } -print "Downloaded $supplementalDataFilename, trying to parse...\n"; +$logger->info( "Downloaded $supplementalDataFilename, trying to parse..." ); $supplementalData = simplexml_load_file( $supplementalDataFilename ); if ( !( $supplementalData instanceof SimpleXMLElement ) ) { - die( "Attempt to load CLDR data from $supplementalDataFilename failed.\n" ); + $logger->error( "Attempt to load CLDR data from $supplementalDataFilename failed." ); + exit( 1 ); } -print "CLDR supplemental data parsed successfully, reading territories info...\n"; +$logger->info( "CLDR supplemental data parsed successfully, reading territories info..." ); $parsedLangdb['territories'] = []; foreach ( $supplementalData->territoryInfo->territory as $territoryRecord ) { @@ -78,14 +95,14 @@ foreach ( $parsedLangdb['territories'] as $territoryCode => $languages ) { foreach ( $languages as $index => $language ) { if ( !isset( $parsedLangdb['languages'][$language] ) ) { - echo "Unknown language $language for territory $territoryCode\n"; + $logger->warning( "Unknown language $language for territory $territoryCode" ); unset( $parsedLangdb['territories'][$territoryCode][$index] ); continue; } $data = $parsedLangdb['languages'][$language]; if ( count( $data ) === 1 ) { - echo "Redirect for language $language to {$data[0]} territory $territoryCode\n"; + $logger->info( "Redirect for language $language to {$data[0]} territory $territoryCode" ); $parsedLangdb['territories'][$territoryCode][$index] = $data[0]; continue; } @@ -106,9 +123,15 @@ array_values( $parsedLangdb['territories'][$territoryCode] ); } -print "Writing JSON langdb...\n"; +$logger->info( "Writing JSON langdb..." ); $jsonVerbose = json_encode( $parsedLangdb, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ) . "\n"; // For making diff review easier. -file_put_contents( DATA_DIRECTORY . '/language-data.json', $jsonVerbose ); +$outputFile = DATA_DIRECTORY . '/language-data.json'; +$realDataDir = realpath( DATA_DIRECTORY ); +if ( $realDataDir && str_starts_with( realpath( dirname( $outputFile ) ), $realDataDir ) ) { + file_put_contents( $outputFile, $jsonVerbose, LOCK_EX ); +} else { + throw new Exception( "Invalid output path" ); +} -print "Done.\n"; +$logger->info( "Done." );