diff --git a/src/config/ncc.yaml b/src/config/ncc.yaml index ee7b398..9f1430a 100644 --- a/src/config/ncc.yaml +++ b/src/config/ncc.yaml @@ -1,3 +1,8 @@ +# NCC Default configuration file, upon installation the installer will generate a new configuration file +# for your system or update the existing configuration file and only overwriting values that are no +# longer applicable to the current version of NCC, incorrect configuration values can cause +# unexpected behavior or bugs. + ncc: # The default data directory that is used by NCC to store packages, # cache, configuration files and other generated files. This includes @@ -21,20 +26,12 @@ php: # issues/backdoors, use this feature for containerized environments enable_environment_configurations: false - # Enables/Disables the injection of NCC's include path - # during the initialization phase allowing you to import - # packages using the `import()` function and other ncc - # API Functions without needing to require NCC's autoloader - # - # This feature is highly recommended to be enabled - enable_include_path: true - git: executable_path: "/usr/bin/git" composer: # When enabled, NCC will use it's builtin version of composer - # to execute composer tasks, if disabled it will fallback to + # to execute composer tasks, if disabled it will fall back to # the `executable_path` option and attempt to use that specified # location of composer enable_internal_composer: true diff --git a/src/installer/installer b/src/installer/installer index 621ee3f..f558d32 100644 --- a/src/installer/installer +++ b/src/installer/installer @@ -100,6 +100,8 @@ } $NCC_AUTO_MODE = ($NCC_ARGS !== null && isset($NCC_ARGS['auto'])); + $NCC_BYPASS_CLI_CHECK = ($NCC_ARGS !== null && isset($NCC_ARGS['bypass-cli-check'])); + $NCC_BYPASS_CHECKSUM = ($NCC_ARGS !== null && isset($NCC_ARGS['bypass-checksum'])); if(isset($NCC_ARGS['help'])) { @@ -108,6 +110,8 @@ new CliHelpSection(['--auto'], 'Automates the installation process'), new CliHelpSection(['--install-composer'], 'Require composer to be installed alongside NCC'), new CliHelpSection(['--install-dir'], 'Specifies the installation directory for NCC'), + new CliHelpSection(['--bypass-cli-check'], 'Bypasses the check for a CLI environment'), + new CliHelpSection(['--bypass-checksum'], 'Bypasses the checksum for the installation files'), ]; $options_padding = Functions::detectParametersPadding($options) + 4; @@ -128,27 +132,30 @@ } // Detect the server API - if(defined('PHP_SAPI')) + if(!$NCC_BYPASS_CLI_CHECK) { - if(strtolower(PHP_SAPI) !== 'cli') + if(defined('PHP_SAPI')) + { + if(strtolower(PHP_SAPI) !== 'cli') + { + print('This installation script is meant to be running in your terminal' . PHP_EOL); + } + } + elseif(function_exists('php_sapi_name') && strtolower(php_sapi_name()) !== 'cli') { print('This installation script is meant to be running in your terminal' . PHP_EOL); } - } - elseif(function_exists('php_sapi_name') && strtolower(php_sapi_name()) !== 'cli') - { - print('This installation script is meant to be running in your terminal' . PHP_EOL); - } - else - { - Console::outWarning( - 'The installer cannot determine the Server API (SAPI), the installer will continue but it is ' . - 'recommended to be running this installer in a terminal' - ); + else + { + Console::outWarning( + 'The installer cannot determine the Server API (SAPI), the installer will continue but it is ' . + 'recommended to be running this installer in a terminal' + ); + } } // Check if running in a TTY - if(stream_isatty(STDERR)) + if(stream_isatty(STDERR) && !$NCC_BYPASS_CLI_CHECK) { Console::outWarning('Your terminal may have some issues rendering the output of this installer'); } @@ -193,39 +200,42 @@ } // Preform the checksum validation - if(!file_exists($NCC_CHECKSUM)) + if(!$NCC_BYPASS_CHECKSUM) { - Console::outWarning('The file \'checksum.bin\' was not found, the contents of the program cannot be verified to be safe'); - } - else - { - Console::out('Running checksum'); - - $checksum = ZiProto::decode(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'checksum.bin')); - $checksum_failed = false; - - foreach($checksum as $path => $hash) + if(!file_exists($NCC_CHECKSUM)) { - if(!file_exists(__DIR__ . DIRECTORY_SEPARATOR . $path)) - { - Console::outError('Cannot check file, \'' . $path . '\' not found.'); - $checksum_failed = true; - } - elseif(hash_file('sha256', __DIR__ . DIRECTORY_SEPARATOR . $path) !== $hash) - { - Console::outWarning('The file \'' . $path . '\' does not match the original checksum'); - $checksum_failed = true; - } - } - - if($checksum_failed) - { - Console::outError('Checksum failed, the contents of the program cannot be verified to be safe'); - exit(1); + Console::outWarning('The file \'checksum.bin\' was not found, the contents of the program cannot be verified to be safe'); } else { - Console::out('Checksum passed'); + Console::out('Running checksum'); + + $checksum = ZiProto::decode(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'checksum.bin')); + $checksum_failed = false; + + foreach($checksum as $path => $hash) + { + if(!file_exists(__DIR__ . DIRECTORY_SEPARATOR . $path)) + { + Console::outError('Cannot check file, \'' . $path . '\' not found.'); + $checksum_failed = true; + } + elseif(hash_file('sha256', __DIR__ . DIRECTORY_SEPARATOR . $path) !== $hash) + { + Console::outWarning('The file \'' . $path . '\' does not match the original checksum'); + $checksum_failed = true; + } + } + + if($checksum_failed) + { + Console::outError('Checksum failed, the contents of the program cannot be verified to be safe'); + exit(1); + } + else + { + Console::out('Checksum passed'); + } } } @@ -514,7 +524,7 @@ // Verify install if(!$NCC_FILESYSTEM->exists([$NCC_INSTALL_PATH . DIRECTORY_SEPARATOR . 'composer.phar'])) { - Console::outError("The installation exited without any issues but composer doesn't seem to be installed correctly"); + Console::outError("Installation failed, the installation exited without any issues but composer doesn't seem to be installed correctly"); exit(1); } diff --git a/src/ncc/Abstracts/CompilerOptions.php b/src/ncc/Abstracts/CompilerOptions.php new file mode 100644 index 0000000..1f4b029 --- /dev/null +++ b/src/ncc/Abstracts/CompilerOptions.php @@ -0,0 +1,8 @@ +""|]*[%])|([a-zA-Z][:])|(\\\\))((\\\\{1})|((\\\\{1})[^\\\\]([^\/:*?<>""|]*))+)$/m'; + + const ConstantName = '/^([^\x00-\x7F]|[\w_\ \.\+\-]){2,16}$/'; } \ No newline at end of file diff --git a/src/ncc/Abstracts/Versions.php b/src/ncc/Abstracts/Versions.php index f579c66..eada0c3 100644 --- a/src/ncc/Abstracts/Versions.php +++ b/src/ncc/Abstracts/Versions.php @@ -9,4 +9,8 @@ */ const CredentialsStoreVersion = '1.0.0'; + /** + * The current version of the package structure file format + */ + const PackageStructureVersion = '1.0.0'; } \ No newline at end of file diff --git a/src/ncc/CLI/Main.php b/src/ncc/CLI/Main.php index 0bf634e..0f61272 100644 --- a/src/ncc/CLI/Main.php +++ b/src/ncc/CLI/Main.php @@ -3,6 +3,9 @@ namespace ncc\CLI; use Exception; + use ncc\Abstracts\NccBuildFlags; + use ncc\Exceptions\FileNotFoundException; + use ncc\Exceptions\RuntimeException; use ncc\ncc; use ncc\Utilities\Console; use ncc\Utilities\Resolver; @@ -22,7 +25,26 @@ if(isset($args['ncc-cli'])) { // Initialize NCC - ncc::initialize(); + try + { + ncc::initialize(); + } + catch (FileNotFoundException $e) + { + Console::outException('Cannot initialize NCC, one or more files were not found.', $e, 1); + } + catch (RuntimeException $e) + { + Console::outException('Cannot initialize NCC due to a runtime error.', $e, 1); + } + + // Define CLI stuff + define('NCC_CLI_MODE', 1); + + if(in_array(NccBuildFlags::Unstable, NCC_VERSION_FLAGS)) + { + Console::outWarning('This is an unstable build of NCC, expect some features to not work as expected'); + } try { diff --git a/src/ncc/Classes/AutoloaderGenerator.php b/src/ncc/Classes/AutoloaderGenerator.php deleted file mode 100644 index feefbe6..0000000 --- a/src/ncc/Classes/AutoloaderGenerator.php +++ /dev/null @@ -1,26 +0,0 @@ -project = $project; - } - - public function generateAutoload(string $src, string $output, bool $static=false) - { - - } - } \ No newline at end of file diff --git a/src/ncc/Classes/Compilers/Php.php b/src/ncc/Classes/Compilers/Php.php new file mode 100644 index 0000000..8d587f4 --- /dev/null +++ b/src/ncc/Classes/Compilers/Php.php @@ -0,0 +1,40 @@ +project = $project; + $this->autoloader = new AutoloaderGenerator($project); + } + + public function prepare(array $options) + { + // TODO: Implement prepare() method. + } + + public function build(array $options) + { + // TODO: Implement build() method. + } + } \ No newline at end of file diff --git a/src/ncc/Classes/PackageParser.php b/src/ncc/Classes/PackageParser.php new file mode 100644 index 0000000..12b18c1 --- /dev/null +++ b/src/ncc/Classes/PackageParser.php @@ -0,0 +1,43 @@ +PackagePath = $path; + $this->parseFile(); + } + + private function parseFile() + { + if(file_exists($this->PackagePath) == false) + { + throw new FileNotFoundException('The given package path \'' . $this->PackagePath . '\' does not exist'); + } + + if(is_file($this->PackagePath) == false) + { + throw new FileNotFoundException('The given package path \'' . $this->PackagePath . '\' is not a file'); + } + + $file_handler = fopen($this->PackagePath, 'rb'); + $header = fread($file_handler, 14); + var_dump($header); + } + } \ No newline at end of file diff --git a/src/ncc/Classes/PhpExtension/AutoloaderGenerator.php b/src/ncc/Classes/PhpExtension/AutoloaderGenerator.php new file mode 100644 index 0000000..ff0e56f --- /dev/null +++ b/src/ncc/Classes/PhpExtension/AutoloaderGenerator.php @@ -0,0 +1,117 @@ +project = $project; + } + + /** + * Processes the project and generates the autoloader source code. + * + * @param string $src + * @param string $output + * @param bool $static + * @return string + * @throws AutoloadGeneratorException + * @throws CollectorException + * @throws Exception + * @throws NoUnitsFoundException + */ + public function generateAutoload(string $src, string $output, bool $static=false): string + { + // Construct configuration + $configuration = new Config([$src]); + $configuration->setFollowSymlinks(false); + $configuration->setOutputFile($output); + $configuration->setTrusting(false); // Paranoid + + // Construct factory + $factory = new Factory(); + $factory->setConfig($configuration); + + // Create Collector + $result = self::runCollector($factory, $configuration); + + // Exception raises when there are no files in the project that can be processed by the autoloader + if(!$result->hasUnits()) + { + throw new NoUnitsFoundException('No units were found in the project'); + } + + if(!$result->hasDuplicates()) + { + foreach($result->getDuplicates() as $unit => $files) + { + Console::outWarning((count($files) -1). ' duplicate unit(s) detected in the project: ' . $unit); + } + } + + $template = @file_get_contents($configuration->getTemplate()); + if ($template === false) + { + throw new AutoloadGeneratorException("Failed to read the template file '" . $configuration->getTemplate() . "'"); + } + + $builder = $factory->getRenderer($result); + return $builder->render($template); + } + + /** + * Iterates through the target directories through the collector and returns the collector results. + * + * @param Factory $factory + * @param Config $config + * @return CollectorResult + * @throws CollectorException + * @throws Exception + */ + private static function runCollector(Factory $factory, Config $config): CollectorResult + { + $collector = $factory->getCollector(); + foreach($config->getDirectories() as $directory) + { + if(is_dir($directory)) + { + $scanner = $factory->getScanner()->getIterator($directory); + $collector->processDirectory($scanner); + unset($scanner); + } + else + { + $file = new SplFileInfo($directory); + $filter = $factory->getFilter(new ArrayIterator(array($file))); + foreach($filter as $file) + { + $collector->processFile($file); + } + } + } + + return $collector->getResult(); + } + + } \ No newline at end of file diff --git a/src/ncc/Classes/PhpExtension/Compiler.php b/src/ncc/Classes/PhpExtension/Compiler.php new file mode 100644 index 0000000..b9ea110 --- /dev/null +++ b/src/ncc/Classes/PhpExtension/Compiler.php @@ -0,0 +1,46 @@ +project = $project; + } + + public function prepare(array $options) + { + if(ncc::cliMode()) + { + Console::out('Building autoloader'); + Console::out('theseer\DirectoryScanner - Copyright (c) 2009-2014 Arne Blankerts All rights reserved.'); + Console::out('theseer\Autoload - Copyright (c) 2010-2016 Arne Blankerts and Contributors All rights reserved.'); + } + + // First scan the project files and create a file struct. + $DirectoryScanner = new DirectoryScanner(); + $DirectoryScanner->unsetFlag(FilesystemIterator::FOLLOW_SYMLINKS); + } + + public function build(array $options) + { + // TODO: Implement build() method. + } + } \ No newline at end of file diff --git a/src/ncc/Exceptions/AutoloadGeneratorException.php b/src/ncc/Exceptions/AutoloadGeneratorException.php new file mode 100644 index 0000000..e260d33 --- /dev/null +++ b/src/ncc/Exceptions/AutoloadGeneratorException.php @@ -0,0 +1,19 @@ +message = $message; + $this->previous = $previous; + } + } \ No newline at end of file diff --git a/src/ncc/Exceptions/InvalidPackageException.php b/src/ncc/Exceptions/InvalidPackageException.php new file mode 100644 index 0000000..04d3ff9 --- /dev/null +++ b/src/ncc/Exceptions/InvalidPackageException.php @@ -0,0 +1,25 @@ +message = $message; + $this->previous = $previous; + } + } \ No newline at end of file diff --git a/src/ncc/Exceptions/NoUnitsFoundException.php b/src/ncc/Exceptions/NoUnitsFoundException.php new file mode 100644 index 0000000..a59e3da --- /dev/null +++ b/src/ncc/Exceptions/NoUnitsFoundException.php @@ -0,0 +1,26 @@ +message = $message; + $this->previous = $previous; + } + } \ No newline at end of file diff --git a/src/ncc/Exceptions/NotImplementedException.php b/src/ncc/Exceptions/NotImplementedException.php new file mode 100644 index 0000000..e53d390 --- /dev/null +++ b/src/ncc/Exceptions/NotImplementedException.php @@ -0,0 +1,28 @@ +message = $message; + $this->previous = $previous; + } + } \ No newline at end of file diff --git a/src/ncc/Exceptions/UnsupportedPackageException.php b/src/ncc/Exceptions/UnsupportedPackageException.php new file mode 100644 index 0000000..e16c0e2 --- /dev/null +++ b/src/ncc/Exceptions/UnsupportedPackageException.php @@ -0,0 +1,25 @@ +message = $message; + $this->previous = $previous; + } + } \ No newline at end of file diff --git a/src/ncc/Interfaces/CompilerInterface.php b/src/ncc/Interfaces/CompilerInterface.php new file mode 100644 index 0000000..d11ec3e --- /dev/null +++ b/src/ncc/Interfaces/CompilerInterface.php @@ -0,0 +1,10 @@ + 0) { + /** @noinspection PhpRedundantOptionalArgumentInspection */ $result = str_pad(implode(' ', $this->Parameters), $param_padding, ' ', STR_PAD_RIGHT); - if($basic == false) + if(!$basic) { $result = Console::formatColor($result, ConsoleColors::Green); } diff --git a/src/ncc/Objects/Constant.php b/src/ncc/Objects/Constant.php index b25df7f..b9c5f78 100644 --- a/src/ncc/Objects/Constant.php +++ b/src/ncc/Objects/Constant.php @@ -3,7 +3,6 @@ namespace ncc\Objects; use ncc\Exceptions\ConstantReadonlyException; - use ncc\Symfony\Component\Uid\Uuid; use ncc\Utilities\Resolver; class Constant @@ -90,6 +89,7 @@ /** * @param string $value + * @param bool $readonly * @throws ConstantReadonlyException */ public function setValue(string $value, bool $readonly=false): void diff --git a/src/ncc/Objects/NccUpdateInformation.php b/src/ncc/Objects/NccUpdateInformation.php index 5d67e36..de3386d 100644 --- a/src/ncc/Objects/NccUpdateInformation.php +++ b/src/ncc/Objects/NccUpdateInformation.php @@ -1,5 +1,7 @@ MagicBytes = new MagicBytes(); + $this->Components = []; + $this->Dependencies = []; + $this->Resources = []; + } + + /** + * Validates the package object and returns True if the package contains the correct information + * + * Returns false if the package contains incorrect information which can cause + * an error when compiling the package. + * + * @param bool $throw_exception + * @return bool + * @throws InvalidPackageException + * @throws InvalidProjectConfigurationException + */ + public function validate(bool $throw_exception=True): bool + { + // Validate the MagicBytes constructor + if($this->MagicBytes == null) + { + if($throw_exception) + throw new InvalidPackageException('The MagicBytes property is required and cannot be null'); + + return false; + } + + // Validate the assembly object + if($this->Assembly == null) + { + if($throw_exception) + throw new InvalidPackageException('The Assembly property is required and cannot be null'); + + return false; + } + + if(!$this->Assembly->validate($throw_exception)) + return false; + + // All checks have passed + return true; + } + + /** + * Constructs an array representation of the object + * + * @param bool $bytecode + * @return array + */ + public function toArray(bool $bytecode=false): array + { + $_components = []; + /** @var Component $component */ + foreach($this->Components as $component) + $_components[] = $component->toArray($bytecode); + + $_dependencies = []; + /** @var Dependency $dependency */ + foreach($this->Dependencies as $dependency) + $_dependencies[] = $dependency->toArray($bytecode); + + $_resources = []; + /** @var Resource $resource */ + foreach($this->Resources as $resource) + $_resources[] = $resource->toArray($bytecode); + + return [ + ($bytecode ? Functions::cbc('header') : 'header') => $this->Header->toArray($bytecode), + ($bytecode ? Functions::cbc('assembly') : 'assembly') => $this->Assembly->toArray($bytecode), + ($bytecode ? Functions::cbc('dependencies') : 'dependencies') => $_dependencies, + ($bytecode ? Functions::cbc('main_execution_policy') : 'main_execution_policy') => $this->MainExecutionPolicy->toArray($bytecode), + ($bytecode ? Functions::cbc('installer') : 'installer') => $this->Installer->toArray($bytecode), + ($bytecode ? Functions::cbc('resources') : 'resources') => $_resources, + ($bytecode ? Functions::cbc('components') : 'components') => $_components + ]; + } + + /** + * @param array $data + * @return Package + */ + public static function fromArray(array $data): self + { + $object = new self(); + + $object->Header = Functions::array_bc($data, 'header'); + if($object->Header !== null) + $object->Header = Header::fromArray($object->Header); + + $object->Assembly = Functions::array_bc($data, 'assembly'); + if($object->Assembly !== null) + $object->Assembly = Assembly::fromArray($object->Assembly); + + $object->MainExecutionPolicy = Functions::array_bc($data, 'main_execution_policy'); + if($object->MainExecutionPolicy !== null) + $object->MainExecutionPolicy = MainExecutionPolicy::fromArray($object->MainExecutionPolicy); + + $object->Installer = Functions::array_bc($data, 'installer'); + if($object->Installer !== null) + $object->Installer = Installer::fromArray($object->Installer); + + $_dependencies = Functions::array_bc($data, 'dependencies'); + if($_dependencies !== null) + { + foreach($_dependencies as $dependency) + { + $object->Dependencies[] = Resource::fromArray($dependency); + } + } + + $_resources = Functions::array_bc($data, 'resources'); + if($_resources !== null) + { + foreach($_resources as $resource) + { + $object->Resources[] = Resource::fromArray($resource); + } + } + + $_components = Functions::array_bc($data, 'components'); + if($_components !== null) + { + foreach($_components as $component) + { + $object->Components[] = Component::fromArray($component); + } + } + + return $object; + } + } \ No newline at end of file diff --git a/src/ncc/Objects/Package/Component.php b/src/ncc/Objects/Package/Component.php new file mode 100644 index 0000000..8752cd4 --- /dev/null +++ b/src/ncc/Objects/Package/Component.php @@ -0,0 +1,91 @@ +Checksum === null) + return false; + + if($this->Data === null) + return false; + + if(hash('sha1', $this->Data) !== $this->Checksum) + return false; + + return true; + } + + /** + * Returns an array representation of the component. + * + * @param bool $bytecode + * @return array + */ + public function toArray(bool $bytecode=false): array + { + return [ + ($bytecode ? Functions::cbc('name') : 'name') => $this->Name, + ($bytecode ? Functions::cbc('flags') : 'flags') => $this->Flags, + ($bytecode ? Functions::cbc('checksum') : 'checksum') => $this->Checksum, + ($bytecode ? Functions::cbc('data') : 'data') => $this->Data, + ]; + } + + /** + * Constructs a new object from an array representation + * + * @param array $data + * @return Component + */ + public static function fromArray(array $data): self + { + $Object = new self(); + + $Object->Name = Functions::array_bc($data, 'name'); + $Object->Flags = Functions::array_bc($data, 'flags'); + $Object->Checksum = Functions::array_bc($data, 'checksum'); + $Object->Data = Functions::array_bc($data, 'data'); + + return $Object; + } + } \ No newline at end of file diff --git a/src/ncc/Objects/Package/Header.php b/src/ncc/Objects/Package/Header.php new file mode 100644 index 0000000..e090bc5 --- /dev/null +++ b/src/ncc/Objects/Package/Header.php @@ -0,0 +1,73 @@ +CompilerExtension = new Compiler(); + $this->RuntimeConstants = []; + } + + /** + * Returns an array representation of the object + * + * @param bool $bytecode + * @return array + */ + public function toArray(bool $bytecode=false): array + { + return [ + ($bytecode ? Functions::cbc('compiler_extension') : 'compiler_extension') => $this->CompilerExtension->toArray($bytecode), + ($bytecode ? Functions::cbc('runtime_constants') : 'runtime_constants') => $this->RuntimeConstants, + ($bytecode ? Functions::cbc('compiler_version') : 'compiler_version') => $this->CompilerVersion, + ]; + } + + /** + * Constructs the object from an array representation + * + * @param array $data + * @return static + */ + public static function fromArray(array $data): self + { + $object = new self(); + + $object->CompilerExtension = Functions::array_bc($data, 'compiler_extension'); + $object->RuntimeConstants = Functions::array_bc($data, 'runtime_constants'); + $object->CompilerVersion = Functions::array_bc($data, 'compiler_version'); + + return $object; + } + } \ No newline at end of file diff --git a/src/ncc/Objects/Package/Installer.php b/src/ncc/Objects/Package/Installer.php new file mode 100644 index 0000000..cbeb8b0 --- /dev/null +++ b/src/ncc/Objects/Package/Installer.php @@ -0,0 +1,30 @@ +PackageStructureVersion = Versions::PackageStructureVersion; + $this->Encoder = EncoderType::ZiProto; + $this->IsCompressed = false; + $this->IsEncrypted = false; + $this->IsInstallable = false; + $this->IsExecutable = false; + } + + /** + * Returns an array representation of the object + * + * @return array + */ + public function toArray(): array + { + return [ + 'package_structure_version' => $this->PackageStructureVersion, + 'encoder' => $this->Encoder, + 'is_compressed' => $this->IsCompressed, + 'is_encrypted' => $this->IsEncrypted, + 'is_installable' => $this->IsInstallable, + 'is_executable' => $this->IsExecutable + ]; + } + + /** + * Constructs object from an array representation + * + * @param array $data + * @return MagicBytes + */ + public static function fromArray(array $data): self + { + $Object = new self(); + + if(isset($data['is_executable'])) + $Object->IsExecutable = (bool)$data['is_executable']; + + return $Object; + } + + /** + * Builds and returns the string representation of the magic bytes + * + * @return string + */ + public function toString(): string + { + // NCC_PACKAGE1.0 + $magic_bytes = 'NCC_PACKAGE' . $this->PackageStructureVersion; + + // NCC_PACKAGE1.03 + $magic_bytes .= $this->Encoder; + + if($this->IsEncrypted) + { + // NCC_PACKAGE1.031 + $magic_bytes .= '1'; + } + else + { + // NCC_PACKAGE1.030 + $magic_bytes .= '0'; + } + + if($this->IsCompressed) + { + // NCC_PACKAGE1.0301 + $magic_bytes .= '1'; + } + else + { + // NCC_PACKAGE1.0300 + $magic_bytes .= '0'; + } + + if($this->IsExecutable && $this->IsInstallable) + { + // NCC_PACKAGE1.030142 + $magic_bytes .= '42'; + } + elseif($this->IsExecutable) + { + // NCC_PACKAGE1.030141 + $magic_bytes .= '41'; + } + elseif($this->IsInstallable) + { + // NCC_PACKAGE1.030140 + $magic_bytes .= '40'; + } + + return $magic_bytes; + } + } \ No newline at end of file diff --git a/src/ncc/Objects/Package/MainExecutionPolicy.php b/src/ncc/Objects/Package/MainExecutionPolicy.php new file mode 100644 index 0000000..c005578 --- /dev/null +++ b/src/ncc/Objects/Package/MainExecutionPolicy.php @@ -0,0 +1,30 @@ +Checksum === null) + return false; + + if($this->Data === null) + return false; + + if(hash('sha1', $this->Data) !== $this->Checksum) + return false; + + return true; + } + + /** + * Returns an array representation of the resource. + * + * @param bool $bytecode + * @return array + */ + public function toArray(bool $bytecode=false): array + { + return [ + ($bytecode ? Functions::cbc('name') : 'name') => $this->Name, + ($bytecode ? Functions::cbc('checksum') : 'checksum') => $this->Checksum, + ($bytecode ? Functions::cbc('data') : 'data') => $this->Data, + ]; + } + + /** + * Constructs a new object from an array representation + * + * @param array $data + * @return Resource + */ + public static function fromArray(array $data): self + { + $object = new self(); + + $object->Name = Functions::array_bc($data, 'name'); + $object->Checksum = Functions::array_bc($data, 'checksum'); + $object->Data = Functions::array_bc($data, 'data'); + + return $object; + } + } \ No newline at end of file diff --git a/src/ncc/Objects/ProjectConfiguration/Assembly.php b/src/ncc/Objects/ProjectConfiguration/Assembly.php index 49541fd..b5eedcf 100644 --- a/src/ncc/Objects/ProjectConfiguration/Assembly.php +++ b/src/ncc/Objects/ProjectConfiguration/Assembly.php @@ -85,7 +85,7 @@ */ public function validate(bool $throw_exception=false): bool { - if(preg_match(RegexPatterns::UUIDv4, $this->UUID) == false) + if(!preg_match(RegexPatterns::UUIDv4, $this->UUID)) { if($throw_exception) throw new InvalidProjectConfigurationException('The UUID is not a valid v4 UUID', 'Assembly.UUID'); @@ -93,7 +93,7 @@ return false; } - if(Validate::version($this->Version) == false) + if(!Validate::version($this->Version)) { if($throw_exception) throw new InvalidProjectConfigurationException('The version number is invalid', 'Assembly.Version'); @@ -101,7 +101,7 @@ return false; } - if(preg_match(RegexPatterns::PackageNameFormat, $this->Package) == false) + if(!preg_match(RegexPatterns::PackageNameFormat, $this->Package)) { if($throw_exception) throw new InvalidProjectConfigurationException('The package name is invalid', 'Assembly.Package'); diff --git a/src/ncc/Runtime/Constants.php b/src/ncc/Runtime/Constants.php index 2e7366a..312b443 100644 --- a/src/ncc/Runtime/Constants.php +++ b/src/ncc/Runtime/Constants.php @@ -1,10 +1,14 @@ isReadonly()) diff --git a/src/ncc/ThirdParty/theseer/Autoload/.idea/.gitignore b/src/ncc/ThirdParty/theseer/Autoload/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/src/ncc/ThirdParty/theseer/Autoload/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/src/ncc/ThirdParty/theseer/Autoload/.idea/Autoload.iml b/src/ncc/ThirdParty/theseer/Autoload/.idea/Autoload.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/src/ncc/ThirdParty/theseer/Autoload/.idea/Autoload.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ncc/ThirdParty/theseer/Autoload/.idea/inspectionProfiles/Project_Default.xml b/src/ncc/ThirdParty/theseer/Autoload/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..ea8af9c --- /dev/null +++ b/src/ncc/ThirdParty/theseer/Autoload/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/src/ncc/ThirdParty/theseer/Autoload/.idea/modules.xml b/src/ncc/ThirdParty/theseer/Autoload/.idea/modules.xml new file mode 100644 index 0000000..ba60841 --- /dev/null +++ b/src/ncc/ThirdParty/theseer/Autoload/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/ncc/ThirdParty/theseer/Autoload/.idea/php.xml b/src/ncc/ThirdParty/theseer/Autoload/.idea/php.xml new file mode 100644 index 0000000..31b8a3a --- /dev/null +++ b/src/ncc/ThirdParty/theseer/Autoload/.idea/php.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/ncc/ThirdParty/theseer/Autoload/.idea/vcs.xml b/src/ncc/ThirdParty/theseer/Autoload/.idea/vcs.xml new file mode 100644 index 0000000..bc59970 --- /dev/null +++ b/src/ncc/ThirdParty/theseer/Autoload/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/ncc/Utilities/Functions.php b/src/ncc/Utilities/Functions.php index b8681fb..d0c3821 100644 --- a/src/ncc/Utilities/Functions.php +++ b/src/ncc/Utilities/Functions.php @@ -29,7 +29,7 @@ */ public static function cbc(string $input): int { - return hexdec(hash('crc32', $input)); + return hexdec(hash('crc32', $input, true)); } /** diff --git a/src/ncc/Utilities/Validate.php b/src/ncc/Utilities/Validate.php index deb1050..3cb7600 100644 --- a/src/ncc/Utilities/Validate.php +++ b/src/ncc/Utilities/Validate.php @@ -187,4 +187,25 @@ return false; } + + /** + * Validates if the constant name is valid + * + * @param $input + * @return bool + */ + public static function constantName($input): bool + { + if($input == null) + { + return false; + } + + if(!preg_match(RegexPatterns::ConstantName, $input)) + { + return false; + } + + return true; + } } \ No newline at end of file diff --git a/src/ncc/autoload.php b/src/ncc/autoload.php index 5d05c62..8f42459 100644 --- a/src/ncc/autoload.php +++ b/src/ncc/autoload.php @@ -8,7 +8,7 @@ * before proceeding to improve performance. */ - if(defined('NCC_INIT') == false) + if(!defined('NCC_INIT')) { $third_party_path = __DIR__ . DIRECTORY_SEPARATOR . 'ThirdParty' . DIRECTORY_SEPARATOR; $target_files = [ @@ -23,14 +23,28 @@ $third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Filesystem' . DIRECTORY_SEPARATOR . 'autoload_spl.php', $third_party_path . 'Symfony' . DIRECTORY_SEPARATOR . 'Yaml' . DIRECTORY_SEPARATOR . 'autoload_spl.php', $third_party_path . 'theseer' . DIRECTORY_SEPARATOR . 'Autoload' . DIRECTORY_SEPARATOR . 'autoload_spl.php', + $third_party_path . 'theseer' . DIRECTORY_SEPARATOR . 'DirectoryScanner' . DIRECTORY_SEPARATOR . 'autoload_spl.php', ]; + $init_success = true; foreach($target_files as $file) { + if(!file_exists($file)) + { + trigger_error('Cannot find file ' . $file, E_USER_WARNING); + $init_success = false; + continue; + } + require_once($file); } - if(\ncc\ncc::initialize() == false) + if(!$init_success) + { + trigger_error('One or more NCC components are missing/failed to load, NCC runtime may not be stable.', E_USER_WARNING); + } + + if(!\ncc\ncc::initialize()) { trigger_error('NCC Failed to initialize', E_USER_WARNING); } diff --git a/src/ncc/ncc.php b/src/ncc/ncc.php index 8b3cb75..9409ac5 100644 --- a/src/ncc/ncc.php +++ b/src/ncc/ncc.php @@ -96,6 +96,23 @@ return true; } + /** + * Determines if NCC is currently in CLI mode or not + * + * @return bool + */ + public static function cliMode(): bool + { + // TODO: Optimize this function to reduce redundant calls + + if(defined('NCC_CLI_MODE') && NCC_CLI_MODE == 1) + { + return true; + } + + return false; + } + /** * Returns the constants set by NCC * @@ -122,6 +139,9 @@ 'NCC_VERSION_BRANCH' => constant('NCC_VERSION_BRANCH'), 'NCC_VERSION_UPDATE_SOURCE' => constant('NCC_VERSION_UPDATE_SOURCE'), 'NCC_VERSION_FLAGS' => constant('NCC_VERSION_FLAGS'), + + // Runtime Information + 'NCC_CLI_MODE' => (defined('NCC_CLI_MODE') ? NCC_CLI_MODE : 0) // May not be set during runtime initialization ]; } } diff --git a/tests/autoload.php b/tests/autoload.php index 836d924..bd2266b 100644 --- a/tests/autoload.php +++ b/tests/autoload.php @@ -6,7 +6,7 @@ if(!file_exists($BuildDirectory) || !is_dir($BuildDirectory)) throw new RuntimeException('Build directory does not exist, to run tests you must build the project.'); - if(!file($AutoloadPath) || is_file($AutoloadPath)) + if(!file($AutoloadPath) || !is_file($AutoloadPath)) throw new RuntimeException('Autoload file does not exist in \'' . $BuildDirectory .'\', to run tests you must build the project.'); require($AutoloadPath); \ No newline at end of file diff --git a/tests/third_party/theseer/directory_scanner.php b/tests/third_party/theseer/directory_scanner.php new file mode 100644 index 0000000..ff28e24 --- /dev/null +++ b/tests/third_party/theseer/directory_scanner.php @@ -0,0 +1,13 @@ +getPath()); + var_dump($item); + } \ No newline at end of file