add: adding ports from the symfony mime component

This commit is contained in:
Patrick Stewart 2024-07-09 10:27:39 -07:00
parent 9b53df9b0d
commit 830fcdf0da
12 changed files with 4138 additions and 0 deletions

View file

@ -0,0 +1,16 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
library;
export 'src/mime_type_guesser_interface.dart';
export 'src/file_binary_mime_type_guesser.dart';
export 'src/file_info_mime_type_guesser.dart';
export 'src/mime_types_interface.dart';
export 'src/mime_types.dart';

View file

@ -0,0 +1,14 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
library;
export 'src/exception/exception_interface.dart';
export 'src/exception/invalid_argument_exception.dart';
export 'src/exception/logic_exception.dart';

View file

@ -0,0 +1,24 @@
// This file is part of the Symfony package.
//
// (c) Fabien Potencier <fabien@symfony.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// In Dart, we don't have a direct equivalent of PHP's namespace.
// Instead, we use library or part directives to organize code.
// For this example, we'll assume this is part of a library called 'symfony_mime'.
// Dart doesn't have a direct equivalent to PHP's Throwable interface.
// Instead, we'll use the Exception class as the base for our interface.
/// Exception interface for the Symfony MIME component.
///
/// This interface is used to mark exceptions specific to the MIME component.
/// It doesn't add any additional methods but serves as a marker interface.
///
/// @author Fabien Potencier <fabien@symfony.com>
abstract class ExceptionInterface implements Exception {
// This interface doesn't declare any methods.
// It's used as a marker interface in Dart, similar to its use in PHP.
}

View file

@ -0,0 +1,13 @@
import 'dart:core';
import 'exception_interface.dart';
/// @author Fabien Potencier <fabien@symfony.com>
class InvalidArgumentException implements Exception, ExceptionInterface {
final String message;
// Constructor in Dart
InvalidArgumentException([this.message = '']);
@override
String toString() => 'InvalidArgumentException: $message';
}

View file

@ -0,0 +1,5 @@
import 'package:protevus_mime/src/exception/exception_interface.dart';
class LogicException extends StateError implements ExceptionInterface {
LogicException(super.message);
}

View file

@ -0,0 +1,95 @@
import 'dart:io';
import 'package:protevus_mime/mime_exception.dart';
import 'package:protevus_mime/mime.dart';
/// This file is part of the Symfony package.
///
/// (c) Fabien Potencier <fabien@symfony.com>
///
/// For the full copyright and license information, please view the LICENSE
/// file that was distributed with this source code.
/// Guesses the MIME type with the binary "file" (only available on *nix).
///
/// @author Bernhard Schussek <bschussek@gmail.com>
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface {
/// The command to run to get the MIME type of a file.
///
/// The $cmd pattern must contain a "%s" string that will be replaced
/// with the file name to guess.
///
/// The command output must start with the MIME type of the file.
final String _cmd;
/// Creates a new [FileBinaryMimeTypeGuesser] instance.
///
/// [cmd] The command to run to get the MIME type of a file.
FileBinaryMimeTypeGuesser([this._cmd = 'file -b --mime -- %s 2>/dev/null']);
@override
bool isGuesserSupported() {
// Dart doesn't have a direct equivalent to PHP's static variables inside methods,
// so we'll use a top-level variable instead.
return isGuesserSupportedCached();
}
@override
Future<String?> guessMimeType(String filePath) async {
if (!File(filePath).existsSync() ||
!File(filePath).statSync().modeString().contains('r')) {
throw InvalidArgumentException(
'The "$filePath" file does not exist or is not readable.');
}
if (!isGuesserSupported()) {
throw LogicException(
'The "${runtimeType.toString()}" guesser is not supported.');
}
final result = await Process.run(
'sh', ['-c', _cmd.replaceFirst('%s', _escapeShellArg(filePath))]);
if (result.exitCode > 0) {
return null;
}
final type = result.stdout.toString().trim();
final match =
RegExp(r'^([a-z0-9\-]+/[a-z0-9\-\+\.]+)', caseSensitive: false)
.firstMatch(type);
if (match == null) {
// it's not a type, but an error message
return null;
}
return match.group(1);
}
String _escapeShellArg(String arg) {
return "'${arg.replaceAll("'", "'\\''")}'";
}
}
bool? _supportedCache;
bool isGuesserSupportedCached() {
if (_supportedCache != null) {
return _supportedCache!;
}
if (Platform.isWindows || !_hasCommand('file')) {
return _supportedCache = false;
}
return _supportedCache = true;
}
bool _hasCommand(String command) {
try {
final result = Process.runSync('which', [command]);
return result.exitCode == 0 && result.stdout.toString().trim().isNotEmpty;
} catch (e) {
return false;
}
}

View file

@ -0,0 +1,55 @@
import 'dart:io';
import 'package:mime/mime.dart' as mime;
import 'package:protevus_mime/mime_exception.dart';
import 'package:protevus_mime/mime.dart';
/// Guesses the MIME type using the MIME package, which is similar to PHP's FileInfo.
///
/// @author Bernhard Schussek <bschussek@gmail.com>
/// Ported to Dart by [Your Name]
class FileInfoMimeTypeGuesser implements MimeTypeGuesserInterface {
/// Constructs a new FileinfoMimeTypeGuesser.
FileInfoMimeTypeGuesser();
@override
bool isGuesserSupported() {
// In Dart, we're using the mime package which is always available if imported
return true;
}
@override
Future<String?> guessMimeType(String path) async {
final file = File(path);
if (!await file.exists() ||
!(await file.stat()).type.toString().contains('file')) {
throw InvalidArgumentException(
'The "$path" file does not exist or is not readable.');
}
if (!isGuesserSupported()) {
throw LogicException(
'The "${runtimeType.toString()}" guesser is not supported.');
}
String? mimeType;
try {
// Using the mime package to guess the MIME type
final bytes = await file.openRead(0, 12).first;
mimeType = mime.lookupMimeType(path, headerBytes: bytes);
} catch (e) {
print('Error guessing MIME type: $e');
return null;
}
if (mimeType != null && mimeType.length % 2 == 0) {
final mimeStart = mimeType.substring(0, mimeType.length ~/ 2);
if (mimeStart + mimeStart == mimeType) {
mimeType = mimeStart;
}
}
return mimeType;
}
}

View file

@ -0,0 +1,22 @@
// This file is part of the Symfony package.
//
// (c) Fabien Potencier <fabien@symfony.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
import 'dart:io';
/// Guesses the MIME type of a file.
///
/// @author Fabien Potencier <fabien@symfony.com>
abstract class MimeTypeGuesserInterface {
/// Returns true if this guesser is supported.
bool isGuesserSupported();
/// Guesses the MIME type of the file with the given path.
///
/// Throws [UnsupportedError] if the guesser is not supported
/// Throws [FileSystemException] if the file does not exist or is not readable
Future<String?> guessMimeType(String path);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
// This file is part of the Symfony package.
//
// (c) Fabien Potencier <fabien@symfony.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
import 'package:protevus_mime/mime.dart';
/// @author Fabien Potencier <fabien@symfony.com>
abstract class MimeTypesInterface implements MimeTypeGuesserInterface {
/// Gets the extensions for the given MIME type in decreasing order of preference.
///
/// Returns a list of strings representing file extensions.
List<String> getExtensions(String mimeType);
/// Gets the MIME types for the given extension in decreasing order of preference.
///
/// Returns a list of strings representing MIME types.
List<String> getMimeTypes(String ext);
}

View file

@ -10,6 +10,7 @@ environment:
# Add regular dependencies here. # Add regular dependencies here.
dependencies: dependencies:
mime: ^1.0.5
# path: ^1.8.0 # path: ^1.8.0
dev_dependencies: dev_dependencies: