diff --git a/.travis.yml b/.travis.yml index 301539f..d7cb7d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ -language: php -php: - - 5.5 - - 5.4 +sudo: required +dist: trusty before_install: - sudo apt-get update @@ -14,7 +12,6 @@ script: - ../scripts/run_tests.sh after_script: - - php composer.phar update satooshi/php-coveralls --dev - php bin/coveralls -v notifications: diff --git a/Symfony/app/.htaccess b/Symfony/app/.htaccess index 3418e55..c9c4d1b 100644 --- a/Symfony/app/.htaccess +++ b/Symfony/app/.htaccess @@ -1 +1,2 @@ -deny from all \ No newline at end of file +deny from all + diff --git a/Symfony/app/AppKernel.php b/Symfony/app/AppKernel.php index 914db81..b9ecdfb 100644 --- a/Symfony/app/AppKernel.php +++ b/Symfony/app/AppKernel.php @@ -20,7 +20,6 @@ public function registerBundles() ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { - $bundles[] = new Acme\DemoBundle\AcmeDemoBundle(); $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); diff --git a/Symfony/app/Resources/autocompletion/complete.py b/Symfony/app/Resources/autocompletion/complete.py index ab9a44f..ed71561 100644 --- a/Symfony/app/Resources/autocompletion/complete.py +++ b/Symfony/app/Resources/autocompletion/complete.py @@ -141,4 +141,4 @@ def __init__(self, fname, line, column, args): log_error(COMPL_TU_LOAD) self.code_completion = \ - self.TU.codeComplete(self.fname, self.line, self.column) + self.TU.codeComplete(self.fname, self.line, self.column, include_macros=True) diff --git a/Symfony/app/SymfonyRequirements.php b/Symfony/app/SymfonyRequirements.php index 0f89996..dd7c278 100644 --- a/Symfony/app/SymfonyRequirements.php +++ b/Symfony/app/SymfonyRequirements.php @@ -77,7 +77,7 @@ public function getTestMessage() } /** - * Returns the help text for resolving the problem + * Returns the help text for resolving the problem. * * @return string The help text */ @@ -119,14 +119,14 @@ class PhpIniRequirement extends Requirement * * @param string $cfgName The configuration name used for ini_get() * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false, - or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement - * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. - This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. - Example: You require a config to be true but PHP later removes this config and defaults it to true internally. - * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) - * @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - * @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) + * @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement */ public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false) { @@ -221,13 +221,13 @@ public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText * * @param string $cfgName The configuration name used for ini_get() * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false, - or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement - * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. - This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. - Example: You require a config to be true but PHP later removes this config and defaults it to true internally. - * @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) - * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) + * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) */ public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) { @@ -239,13 +239,13 @@ public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = * * @param string $cfgName The configuration name used for ini_get() * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false, - or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement - * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. - This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. - Example: You require a config to be true but PHP later removes this config and defaults it to true internally. - * @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) - * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) + * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) */ public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) { @@ -530,11 +530,22 @@ function_exists('simplexml_import_dom'), /* optional recommendations follow */ - $this->addRecommendation( - file_get_contents(__FILE__) === file_get_contents(__DIR__.'/../vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/skeleton/app/SymfonyRequirements.php'), - 'Requirements file should be up-to-date', - 'Your requirements file is outdated. Run composer install and re-check your configuration.' - ); + if (file_exists(__DIR__.'/../vendor/composer')) { + require_once __DIR__.'/../vendor/autoload.php'; + + try { + $r = new \ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle'); + + $contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php'); + } catch (\ReflectionException $e) { + $contents = ''; + } + $this->addRecommendation( + file_get_contents(__FILE__) === $contents, + 'Requirements file should be up-to-date', + 'Your requirements file is outdated. Run composer install and re-check your configuration.' + ); + } $this->addRecommendation( version_compare($installedPhpVersion, '5.3.4', '>='), @@ -614,15 +625,15 @@ class_exists('Locale'), 'Install and enable the intl extension (used for validators).' ); - if (class_exists('Collator')) { + if (extension_loaded('intl')) { + // in some WAMP server installations, new Collator() returns null $this->addRecommendation( null !== new Collator('fr_FR'), 'intl extension should be correctly configured', 'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.' ); - } - if (class_exists('Locale')) { + // check for compatible ICU versions (only done when you have the intl extension) if (defined('INTL_ICU_VERSION')) { $version = INTL_ICU_VERSION; } else { @@ -641,6 +652,14 @@ class_exists('Locale'), 'intl ICU version should be at least 4+', 'Upgrade your intl extension with a newer ICU version (4+).' ); + + $this->addPhpIniRecommendation( + 'intl.error_level', + create_function('$cfgValue', 'return (int) $cfgValue === 0;'), + true, + 'intl.error_level should be 0 in php.ini', + 'Set "intl.error_level" to "0" in php.ini* to inhibit the messages when an error occurs in ICU functions.' + ); } $accelerator = diff --git a/Symfony/app/config/parameters.yml.dist b/Symfony/app/config/parameters.yml.dist index 7218794..69680b1 100644 --- a/Symfony/app/config/parameters.yml.dist +++ b/Symfony/app/config/parameters.yml.dist @@ -1,16 +1,4 @@ parameters: -# database_driver: pdo_mysql -# database_host: 127.0.0.1 -# database_port: ~ -# database_name: symfony -# database_user: root -# database_password: ~ -# -# mailer_transport: smtp -# mailer_host: 127.0.0.1 -# mailer_user: ~ -# mailer_password: ~ - locale: en secret: CSRF-Token-Not-Really-Used diff --git a/Symfony/app/config/routing_dev.yml b/Symfony/app/config/routing_dev.yml index c45f361..ff93a02 100644 --- a/Symfony/app/config/routing_dev.yml +++ b/Symfony/app/config/routing_dev.yml @@ -12,7 +12,3 @@ _configurator: _main: resource: routing.yml - -# AcmeDemoBundle routes (to be removed) -_acme_demo: - resource: "@AcmeDemoBundle/Resources/config/routing.yml" diff --git a/Symfony/app/config/security.yml b/Symfony/app/config/security.yml index 243aa71..e083cf3 100644 --- a/Symfony/app/config/security.yml +++ b/Symfony/app/config/security.yml @@ -1,39 +1,8 @@ security: - encoders: - Symfony\Component\Security\Core\User\User: plaintext - - role_hierarchy: - ROLE_ADMIN: ROLE_USER - ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] + firewalls: + anonymous: + anonymous: ~ providers: in_memory: memory: - users: - user: { password: userpass, roles: [ 'ROLE_USER' ] } - admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } - - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: false - - login: - pattern: ^/demo/secured/login$ - security: false - - secured_area: - pattern: ^/demo/secured/ - form_login: - check_path: _security_check - login_path: _demo_login - logout: - path: _demo_logout - target: _demo - #anonymous: ~ - #http_basic: - # realm: "Secured Demo Area" - - access_control: - - { path: ^/demo/secured/hello/admin/, roles: ROLE_ADMIN } - #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https } diff --git a/Symfony/composer.json b/Symfony/composer.json index ac51451..7e5aba8 100644 --- a/Symfony/composer.json +++ b/Symfony/composer.json @@ -20,14 +20,17 @@ "sensio/generator-bundle": "2.3.*", "incenteev/composer-parameter-handler": "~2.0" }, - "require-dev": { - "phpunit/phpunit": "3.7.*", - "satooshi/php-coveralls": "dev-master", - "squizlabs/php_codesniffer": "1.*", - "sebastian/phpcpd": "*", - "phpmd/phpmd": "2.0.*" - }, - "scripts": { + "require-dev": { + "phpunit/phpunit": "4.8.*", + "satooshi/php-coveralls": "dev-master", + "squizlabs/php_codesniffer": "1.*", + "sebastian/phpcpd": "*", + "phpmd/phpmd" : "2.0.*", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-token-stream": "~1.3", + "phpunit/phpunit-mock-objects": "~2.3" + }, + "scripts": { "post-install-cmd": [ "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", diff --git a/Symfony/composer.lock b/Symfony/composer.lock index 02d882c..8c4e5c7 100644 --- a/Symfony/composer.lock +++ b/Symfony/composer.lock @@ -1,23 +1,24 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "b11ca2a2df0d63d663c78df83a019a5d", + "hash": "2318058901bc2700202f85be5d1f073a", + "content-hash": "761a74df0b1f8f51c1b0b7afbb0b7320", "packages": [ { "name": "doctrine/annotations", - "version": "v1.2.3", + "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "eeda578cbe24a170331a1cfdf78be723412df7a4" + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/eeda578cbe24a170331a1cfdf78be723412df7a4", - "reference": "eeda578cbe24a170331a1cfdf78be723412df7a4", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", + "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", "shasum": "" }, "require": { @@ -72,20 +73,20 @@ "docblock", "parser" ], - "time": "2014-12-20 20:49:38" + "time": "2015-08-31 12:32:49" }, { "name": "doctrine/cache", - "version": "v1.4.0", + "version": "v1.4.2", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "2346085d2b027b233ae1d5de59b07440b9f288c8" + "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/2346085d2b027b233ae1d5de59b07440b9f288c8", - "reference": "2346085d2b027b233ae1d5de59b07440b9f288c8", + "url": "https://api.github.com/repos/doctrine/cache/zipball/8c434000f420ade76a07c64cbe08ca47e5c101ca", + "reference": "8c434000f420ade76a07c64cbe08ca47e5c101ca", "shasum": "" }, "require": { @@ -96,13 +97,13 @@ }, "require-dev": { "phpunit/phpunit": ">=3.7", - "predis/predis": "~0.8", + "predis/predis": "~1.0", "satooshi/php-coveralls": "~0.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.5.x-dev" } }, "autoload": { @@ -142,25 +143,28 @@ "cache", "caching" ], - "time": "2015-01-15 20:38:55" + "time": "2015-08-31 12:36:41" }, { "name": "doctrine/collections", - "version": "v1.2", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "b99c5c46c87126201899afe88ec490a25eedd6a2" + "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/b99c5c46c87126201899afe88ec490a25eedd6a2", - "reference": "b99c5c46c87126201899afe88ec490a25eedd6a2", + "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a", + "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a", "shasum": "" }, "require": { "php": ">=5.3.2" }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, "type": "library", "extra": { "branch-alias": { @@ -177,17 +181,6 @@ "MIT" ], "authors": [ - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com", - "homepage": "http://www.jwage.com/", - "role": "Creator" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com", - "homepage": "http://www.instaclick.com" - }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -196,11 +189,17 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, { "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", - "role": "Developer of wrapped JMSSerializerBundle" + "email": "schmittjoh@gmail.com" } ], "description": "Collections Abstraction library", @@ -210,20 +209,20 @@ "collections", "iterator" ], - "time": "2014-02-03 23:07:43" + "time": "2015-04-14 22:21:58" }, { "name": "doctrine/common", - "version": "v2.4.2", + "version": "v2.4.3", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "5db6ab40e4c531f14dad4ca96a394dfce5d4255b" + "reference": "4824569127daa9784bf35219a1cd49306c795389" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/5db6ab40e4c531f14dad4ca96a394dfce5d4255b", - "reference": "5db6ab40e4c531f14dad4ca96a394dfce5d4255b", + "url": "https://api.github.com/repos/doctrine/common/zipball/4824569127daa9784bf35219a1cd49306c795389", + "reference": "4824569127daa9784bf35219a1cd49306c795389", "shasum": "" }, "require": { @@ -253,17 +252,6 @@ "MIT" ], "authors": [ - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com", - "homepage": "http://www.jwage.com/", - "role": "Creator" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com", - "homepage": "http://www.instaclick.com" - }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -272,11 +260,17 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, { "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com", - "homepage": "https://github.com/schmittjoh", - "role": "Developer of wrapped JMSSerializerBundle" + "email": "schmittjoh@gmail.com" } ], "description": "Common Library for Doctrine projects", @@ -288,7 +282,7 @@ "persistence", "spl" ], - "time": "2014-05-21 19:28:51" + "time": "2015-08-31 14:38:45" }, { "name": "doctrine/dbal", @@ -362,7 +356,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/v1.2.0", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/765b0d87fcc3e839c74817b7211258cbef3a4fb9", "reference": "v1.2.0", "shasum": "" }, @@ -615,17 +609,16 @@ }, { "name": "incenteev/composer-parameter-handler", - "version": "v2.1.0", - "target-dir": "Incenteev/ParameterHandler", + "version": "v2.1.1", "source": { "type": "git", "url": "https://github.com/Incenteev/ParameterHandler.git", - "reference": "143272a0a09c62616a3c8011fc165a10c6b35241" + "reference": "84a205fe80a46101607bafbc423019527893ddd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Incenteev/ParameterHandler/zipball/143272a0a09c62616a3c8011fc165a10c6b35241", - "reference": "143272a0a09c62616a3c8011fc165a10c6b35241", + "url": "https://api.github.com/repos/Incenteev/ParameterHandler/zipball/84a205fe80a46101607bafbc423019527893ddd0", + "reference": "84a205fe80a46101607bafbc423019527893ddd0", "shasum": "" }, "require": { @@ -644,8 +637,8 @@ } }, "autoload": { - "psr-0": { - "Incenteev\\ParameterHandler": "" + "psr-4": { + "Incenteev\\ParameterHandler\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -663,7 +656,7 @@ "keywords": [ "parameters management" ], - "time": "2013-12-07 10:10:39" + "time": "2015-06-03 08:27:03" }, { "name": "jdorn/sql-formatter", @@ -788,16 +781,16 @@ }, { "name": "monolog/monolog", - "version": "1.12.0", + "version": "1.17.2", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f" + "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f", - "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bee7f0dc9c3e0b69a6039697533dca1e845c8c24", + "reference": "bee7f0dc9c3e0b69a6039697533dca1e845c8c24", "shasum": "" }, "require": { @@ -808,12 +801,16 @@ "psr/log-implementation": "1.0.0" }, "require-dev": { - "aws/aws-sdk-php": "~2.4, >2.4.8", + "aws/aws-sdk-php": "^2.4.9", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", - "phpunit/phpunit": "~4.0", - "raven/raven": "~0.5", - "ruflin/elastica": "0.90.*", + "jakub-onderka/php-parallel-lint": "0.9", + "php-console/php-console": "^3.1.3", + "phpunit/phpunit": "~4.5", + "phpunit/phpunit-mock-objects": "2.3.0", + "raven/raven": "^0.13", + "ruflin/elastica": ">=0.90 <3.0", + "swiftmailer/swiftmailer": "~5.3", "videlalvaro/php-amqplib": "~2.4" }, "suggest": { @@ -822,6 +819,7 @@ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", "ext-mongo": "Allow sending log messages to a MongoDB server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "php-console/php-console": "Allow sending log messages to Google Chrome", "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server", @@ -830,7 +828,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.12.x-dev" + "dev-master": "1.16.x-dev" } }, "autoload": { @@ -856,19 +854,19 @@ "logging", "psr-3" ], - "time": "2014-12-29 21:29:35" + "time": "2015-10-14 12:51:02" }, { "name": "psr/log", "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log", + "url": "https://github.com/php-fig/log.git", "reference": "1.0.0" }, "dist": { "type": "zip", - "url": "https://github.com/php-fig/log/archive/1.0.0.zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", "reference": "1.0.0", "shasum": "" }, @@ -898,17 +896,17 @@ }, { "name": "sensio/distribution-bundle", - "version": "v2.3.8", + "version": "v2.3.22", "target-dir": "Sensio/Bundle/DistributionBundle", "source": { "type": "git", "url": "https://github.com/sensiolabs/SensioDistributionBundle.git", - "reference": "9a72f821957141ee3d9703da3fa8266d59ef4b1c" + "reference": "98bdda791e7c2dfb5fd55781e69a4b00e4f751a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/9a72f821957141ee3d9703da3fa8266d59ef4b1c", - "reference": "9a72f821957141ee3d9703da3fa8266d59ef4b1c", + "url": "https://api.github.com/repos/sensiolabs/SensioDistributionBundle/zipball/98bdda791e7c2dfb5fd55781e69a4b00e4f751a6", + "reference": "98bdda791e7c2dfb5fd55781e69a4b00e4f751a6", "shasum": "" }, "require": { @@ -940,7 +938,7 @@ "configuration", "distribution" ], - "time": "2015-01-07 07:11:03" + "time": "2015-06-05 22:32:08" }, { "name": "sensio/framework-extra-bundle", @@ -1043,28 +1041,28 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v5.3.1", + "version": "v5.4.1", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "c5f963e7f9d6f6438fda4f22d5cc2db296ec621a" + "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/c5f963e7f9d6f6438fda4f22d5cc2db296ec621a", - "reference": "c5f963e7f9d6f6438fda4f22d5cc2db296ec621a", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/0697e6aa65c83edf97bb0f23d8763f94e3f11421", + "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "mockery/mockery": "~0.9.1" + "mockery/mockery": "~0.9.1,<0.9.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3-dev" + "dev-master": "5.4-dev" } }, "autoload": { @@ -1088,10 +1086,11 @@ "description": "Swiftmailer, free feature-rich PHP mailer", "homepage": "http://swiftmailer.org", "keywords": [ + "email", "mail", "mailer" ], - "time": "2014-12-05 14:17:14" + "time": "2015-06-06 14:19:39" }, { "name": "symfony/assetic-bundle", @@ -1099,12 +1098,12 @@ "target-dir": "Symfony/Bundle/AsseticBundle", "source": { "type": "git", - "url": "https://github.com/symfony/AsseticBundle.git", + "url": "https://github.com/symfony/assetic-bundle.git", "reference": "099e0bb5d80e7039af20db384a41017fde521f21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/AsseticBundle/zipball/099e0bb5d80e7039af20db384a41017fde521f21", + "url": "https://api.github.com/repos/symfony/assetic-bundle/zipball/099e0bb5d80e7039af20db384a41017fde521f21", "reference": "099e0bb5d80e7039af20db384a41017fde521f21", "shasum": "" }, @@ -1162,12 +1161,12 @@ "target-dir": "Symfony/Bundle/MonologBundle", "source": { "type": "git", - "url": "https://github.com/symfony/MonologBundle.git", - "reference": "v2.3.0" + "url": "https://github.com/symfony/monolog-bundle.git", + "reference": "03ed73bc11367b3156cc21f22ac37c7f70fcd10a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/MonologBundle/zipball/v2.3.0", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/03ed73bc11367b3156cc21f22ac37c7f70fcd10a", "reference": "v2.3.0", "shasum": "" }, @@ -1219,12 +1218,12 @@ "version": "v2.3.8", "source": { "type": "git", - "url": "https://github.com/symfony/SwiftmailerBundle.git", + "url": "https://github.com/symfony/swiftmailer-bundle.git", "reference": "970b13d01871207e81d17b17ddda025e7e21e797" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/SwiftmailerBundle/zipball/970b13d01871207e81d17b17ddda025e7e21e797", + "url": "https://api.github.com/repos/symfony/swiftmailer-bundle/zipball/970b13d01871207e81d17b17ddda025e7e21e797", "reference": "970b13d01871207e81d17b17ddda025e7e21e797", "shasum": "" }, @@ -1273,23 +1272,23 @@ }, { "name": "symfony/symfony", - "version": "v2.3.24", + "version": "v2.3.33", "source": { "type": "git", "url": "https://github.com/symfony/symfony.git", - "reference": "5b2c33be25fdb94233e2c2625ee2d69289f24300" + "reference": "3b8a8ee48e8ad81cb5d9d85b909bbd28011423a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/symfony/zipball/5b2c33be25fdb94233e2c2625ee2d69289f24300", - "reference": "5b2c33be25fdb94233e2c2625ee2d69289f24300", + "url": "https://api.github.com/repos/symfony/symfony/zipball/3b8a8ee48e8ad81cb5d9d85b909bbd28011423a1", + "reference": "3b8a8ee48e8ad81cb5d9d85b909bbd28011423a1", "shasum": "" }, "require": { - "doctrine/common": "~2.3", + "doctrine/common": "~2.4", "php": ">=5.3.3", "psr/log": "~1.0", - "twig/twig": "~1.12,>=1.12.3" + "twig/twig": "~1.20|~2.0" }, "replace": { "symfony/browser-kit": "self.version", @@ -1332,12 +1331,13 @@ }, "require-dev": { "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.2", - "doctrine/orm": "~2.2,>=2.2.3", + "doctrine/dbal": "~2.4", + "doctrine/orm": "~2.4,>=2.4.5", "ircmaxell/password-compat": "~1.0", "monolog/monolog": "~1.3", "ocramius/proxy-manager": "~0.3.1", - "propel/propel1": "~1.6" + "propel/propel1": "~1.6", + "symfony/phpunit-bridge": "~2.7" }, "type": "library", "extra": { @@ -1362,21 +1362,21 @@ "MIT" ], "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "The Symfony PHP framework", - "homepage": "http://symfony.com", + "homepage": "https://symfony.com", "keywords": [ "framework" ], - "time": "2015-01-07 10:32:09" + "time": "2015-09-25 09:08:49" }, { "name": "twig/extensions", @@ -1427,25 +1427,29 @@ }, { "name": "twig/twig", - "version": "v1.17.0", + "version": "v1.22.3", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "2493970fa4d587eca73f77e6d8bd48a8bdd4c608" + "reference": "ebfc36b7e77b0c1175afe30459cf943010245540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/2493970fa4d587eca73f77e6d8bd48a8bdd4c608", - "reference": "2493970fa4d587eca73f77e6d8bd48a8bdd4c608", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/ebfc36b7e77b0c1175afe30459cf943010245540", + "reference": "ebfc36b7e77b0c1175afe30459cf943010245540", "shasum": "" }, "require": { - "php": ">=5.2.4" + "php": ">=5.2.7" + }, + "require-dev": { + "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "~2.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.17-dev" + "dev-master": "1.22-dev" } }, "autoload": { @@ -1480,22 +1484,76 @@ "keywords": [ "templating" ], - "time": "2015-01-14 10:15:49" + "time": "2015-10-13 07:07:02" } ], "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, { "name": "guzzle/guzzle", - "version": "v3.9.2", + "version": "v3.9.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle3.git", - "reference": "54991459675c1a2924122afbb0e5609ade581155" + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/54991459675c1a2924122afbb0e5609ade581155", - "reference": "54991459675c1a2924122afbb0e5609ade581155", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", "shasum": "" }, "require": { @@ -1536,6 +1594,9 @@ "zendframework/zend-cache": "2.*,<2.3", "zendframework/zend-log": "2.*,<2.3" }, + "suggest": { + "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." + }, "type": "library", "extra": { "branch-alias": { @@ -1563,7 +1624,7 @@ "homepage": "https://github.com/guzzle/guzzle/contributors" } ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", "homepage": "http://guzzlephp.org/", "keywords": [ "client", @@ -1574,7 +1635,7 @@ "rest", "web service" ], - "time": "2014-08-11 04:32:36" + "time": "2015-03-18 18:23:50" }, { "name": "pdepend/pdepend", @@ -1615,6 +1676,55 @@ "description": "Official version of pdepend to be handled with Composer", "time": "2014-10-08 06:54:50" }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", + "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2015-02-03 12:10:50" + }, { "name": "phpmd/phpmd", "version": "2.0.0", @@ -1657,48 +1767,109 @@ "description": "Official version of PHPMD handled with Composer.", "time": "2014-05-21 12:45:23" }, + { + "name": "phpspec/prophecy", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "phpdocumentor/reflection-docblock": "~2.0", + "sebastian/comparator": "~1.1" + }, + "require-dev": { + "phpspec/phpspec": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2015-08-13 10:07:40" + }, { "name": "phpunit/php-code-coverage", - "version": "1.2.18", + "version": "2.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-text-template": ">=1.2.0@stable", - "phpunit/php-token-stream": ">=1.1.3,<1.3.0" + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*@dev" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.0.5" + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -1716,35 +1887,37 @@ "testing", "xunit" ], - "time": "2014-09-02 10:13:14" + "time": "2015-10-06 15:47:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.3.4", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { "classmap": [ - "File/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -1761,20 +1934,20 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -1783,20 +1956,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -1805,20 +1975,20 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", "shasum": "" }, "require": { @@ -1827,13 +1997,10 @@ "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -1849,49 +2016,48 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2015-06-21 08:01:12" }, { "name": "phpunit/php-token-stream", - "version": "1.2.2", + "version": "1.4.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", @@ -1899,62 +2065,61 @@ "keywords": [ "tokenizer" ], - "time": "2014-03-03 05:10:30" + "time": "2015-09-15 10:49:45" }, { "name": "phpunit/phpunit", - "version": "3.7.38", + "version": "4.8.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" + "reference": "be067d6105286b74272facefc2697038f8807b77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/be067d6105286b74272facefc2697038f8807b77", + "reference": "be067d6105286b74272facefc2697038f8807b77", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-dom": "*", "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpunit/php-code-coverage": "~1.2", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.1", - "phpunit/php-timer": "~1.0", - "phpunit/phpunit-mock-objects": "~1.2", - "symfony/yaml": "~2.0" - }, - "require-dev": { - "pear-pear.php.net/pear": "1.9.4" + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": ">=1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" }, "bin": [ - "composer/bin/phpunit" + "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.7.x-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], @@ -1966,45 +2131,52 @@ } ], "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], - "time": "2014-10-17 09:04:17" + "time": "2015-10-14 13:49:40" }, { "name": "phpunit/phpunit-mock-objects", - "version": "1.2.3", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.0.2", "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -2021,7 +2193,7 @@ "mock", "xunit" ], - "time": "2013-01-13 10:24:48" + "time": "2015-10-02 06:51:40" }, { "name": "satooshi/php-coveralls", @@ -2098,23 +2270,255 @@ ], "time": "2014-11-11 15:35:34" }, + { + "name": "sebastian/comparator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", + "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2015-07-26 15:48:44" + }, + { + "name": "sebastian/diff", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-02-22 15:13:53" + }, + { + "name": "sebastian/environment", + "version": "1.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44", + "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2015-08-03 06:14:51" + }, + { + "name": "sebastian/exporter", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", + "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2015-06-21 07:55:53" + }, { "name": "sebastian/finder-facade", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/finder-facade.git", - "reference": "1e396fda3449fce9df032749fa4fa2619e0347e0" + "reference": "a520dcc3dd39160eea480daa3426f4fd419a327b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/1e396fda3449fce9df032749fa4fa2619e0347e0", - "reference": "1e396fda3449fce9df032749fa4fa2619e0347e0", + "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/a520dcc3dd39160eea480daa3426f4fd419a327b", + "reference": "a520dcc3dd39160eea480daa3426f4fd419a327b", "shasum": "" }, "require": { - "symfony/finder": ">=2.2.0", - "theseer/fdomdocument": ">=1.3.1" + "symfony/finder": "~2.3", + "theseer/fdomdocument": "~1.3" }, "type": "library", "autoload": { @@ -2135,28 +2539,79 @@ ], "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", "homepage": "https://github.com/sebastianbergmann/finder-facade", - "time": "2013-05-28 06:10:03" + "time": "2015-06-04 08:11:58" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" }, { "name": "sebastian/phpcpd", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpcpd.git", - "reference": "a9462153f2dd90466a010179901d31fbff598365" + "reference": "d3ad100fdf15805495f6ff19f473f4314c99390c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/a9462153f2dd90466a010179901d31fbff598365", - "reference": "a9462153f2dd90466a010179901d31fbff598365", + "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/d3ad100fdf15805495f6ff19f473f4314c99390c", + "reference": "d3ad100fdf15805495f6ff19f473f4314c99390c", "shasum": "" }, "require": { "php": ">=5.3.3", - "phpunit/php-timer": ">=1.0.4", - "sebastian/finder-facade": ">=1.1.0", - "sebastian/version": ">=1.0.3", - "symfony/console": ">=2.2.0", + "phpunit/php-timer": "~1.0", + "sebastian/finder-facade": "~1.1", + "sebastian/version": "~1.0", + "symfony/console": "~2.2", "theseer/fdomdocument": "~1.4" }, "bin": [ @@ -2186,20 +2641,73 @@ ], "description": "Copy/Paste Detector (CPD) for PHP code.", "homepage": "https://github.com/sebastianbergmann/phpcpd", - "time": "2014-03-31 09:25:30" + "time": "2015-03-26 14:47:38" + }, + { + "name": "sebastian/recursion-context", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", + "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2015-06-21 08:04:50" }, { "name": "sebastian/version", - "version": "1.0.4", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", @@ -2221,7 +2729,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2014-12-15 14:25:24" + "time": "2015-06-21 13:59:46" }, { "name": "squizlabs/php_codesniffer", @@ -2300,16 +2808,16 @@ }, { "name": "theseer/fdomdocument", - "version": "1.6.0", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/theseer/fDOMDocument.git", - "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef" + "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d08cf070350f884c63fc9078d27893c2ab6c7cef", - "reference": "d08cf070350f884c63fc9078d27893c2ab6c7cef", + "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d9ad139d6c2e8edf5e313ffbe37ff13344cf0684", + "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684", "shasum": "" }, "require": { @@ -2336,7 +2844,7 @@ ], "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", "homepage": "https://github.com/theseer/fDOMDocument", - "time": "2014-09-13 10:57:19" + "time": "2015-05-27 22:58:02" } ], "aliases": [], diff --git a/Symfony/src/.htaccess b/Symfony/src/.htaccess index 3418e55..c9c4d1b 100644 --- a/Symfony/src/.htaccess +++ b/Symfony/src/.htaccess @@ -1 +1,2 @@ -deny from all \ No newline at end of file +deny from all + diff --git a/Symfony/src/Acme/DemoBundle/AcmeDemoBundle.php b/Symfony/src/Acme/DemoBundle/AcmeDemoBundle.php deleted file mode 100644 index 269fc1e..0000000 --- a/Symfony/src/Acme/DemoBundle/AcmeDemoBundle.php +++ /dev/null @@ -1,9 +0,0 @@ - $name); - } - - /** - * @Route("/contact", name="_demo_contact") - * @Template() - */ - public function contactAction() - { - $form = $this->get('form.factory')->create(new ContactType()); - - $request = $this->get('request'); - if ($request->isMethod('POST')) { - $form->submit($request); - if ($form->isValid()) { - $mailer = $this->get('mailer'); - // .. setup a message and send it - // http://symfony.com/doc/current/cookbook/email.html - - $this->get('session')->getFlashBag()->set('notice', 'Message sent!'); - - return new RedirectResponse($this->generateUrl('_demo')); - } - } - - return array('form' => $form->createView()); - } -} diff --git a/Symfony/src/Acme/DemoBundle/Controller/SecuredController.php b/Symfony/src/Acme/DemoBundle/Controller/SecuredController.php deleted file mode 100644 index f6d3005..0000000 --- a/Symfony/src/Acme/DemoBundle/Controller/SecuredController.php +++ /dev/null @@ -1,68 +0,0 @@ -attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { - $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); - } else { - $error = $request->getSession()->get(SecurityContext::AUTHENTICATION_ERROR); - } - - return array( - 'last_username' => $request->getSession()->get(SecurityContext::LAST_USERNAME), - 'error' => $error, - ); - } - - /** - * @Route("/login_check", name="_security_check") - */ - public function securityCheckAction() - { - // The security layer will intercept this request - } - - /** - * @Route("/logout", name="_demo_logout") - */ - public function logoutAction() - { - // The security layer will intercept this request - } - - /** - * @Route("/hello", defaults={"name"="World"}), - * @Route("/hello/{name}", name="_demo_secured_hello") - * @Template() - */ - public function helloAction($name) - { - return array('name' => $name); - } - - /** - * @Route("/hello/admin/{name}", name="_demo_secured_hello_admin") - * @Template() - */ - public function helloadminAction($name) - { - return array('name' => $name); - } -} diff --git a/Symfony/src/Acme/DemoBundle/Controller/WelcomeController.php b/Symfony/src/Acme/DemoBundle/Controller/WelcomeController.php deleted file mode 100644 index acceedf..0000000 --- a/Symfony/src/Acme/DemoBundle/Controller/WelcomeController.php +++ /dev/null @@ -1,18 +0,0 @@ -render('AcmeDemoBundle:Welcome:index.html.twig'); - } -} diff --git a/Symfony/src/Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php b/Symfony/src/Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php deleted file mode 100644 index 6dfcc82..0000000 --- a/Symfony/src/Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php +++ /dev/null @@ -1,22 +0,0 @@ -load('services.xml'); - } - - public function getAlias() - { - return 'acme_demo'; - } -} diff --git a/Symfony/src/Acme/DemoBundle/EventListener/ControllerListener.php b/Symfony/src/Acme/DemoBundle/EventListener/ControllerListener.php deleted file mode 100644 index aa117d7..0000000 --- a/Symfony/src/Acme/DemoBundle/EventListener/ControllerListener.php +++ /dev/null @@ -1,24 +0,0 @@ -extension = $extension; - } - - public function onKernelController(FilterControllerEvent $event) - { - if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) { - $this->extension->setController($event->getController()); - } - } -} diff --git a/Symfony/src/Acme/DemoBundle/Form/ContactType.php b/Symfony/src/Acme/DemoBundle/Form/ContactType.php deleted file mode 100644 index 2c76cdb..0000000 --- a/Symfony/src/Acme/DemoBundle/Form/ContactType.php +++ /dev/null @@ -1,20 +0,0 @@ -add('email', 'email'); - $builder->add('message', 'textarea'); - } - - public function getName() - { - return 'contact'; - } -} diff --git a/Symfony/src/Acme/DemoBundle/Resources/config/routing.yml b/Symfony/src/Acme/DemoBundle/Resources/config/routing.yml deleted file mode 100644 index f95dc84..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/config/routing.yml +++ /dev/null @@ -1,12 +0,0 @@ -_welcome: - pattern: / - defaults: { _controller: AcmeDemoBundle:Welcome:index } - -_demo_secured: - resource: "@AcmeDemoBundle/Controller/SecuredController.php" - type: annotation - -_demo: - resource: "@AcmeDemoBundle/Controller/DemoController.php" - type: annotation - prefix: /demo diff --git a/Symfony/src/Acme/DemoBundle/Resources/config/services.xml b/Symfony/src/Acme/DemoBundle/Resources/config/services.xml deleted file mode 100644 index d6274ce..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/config/services.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/css/demo.css b/Symfony/src/Acme/DemoBundle/Resources/public/css/demo.css deleted file mode 100644 index 4dd2f16..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/public/css/demo.css +++ /dev/null @@ -1,101 +0,0 @@ -body { - font-size: 14px; - font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; -} -h1.title { - font-size: 45px; - padding-bottom: 30px; -} -.sf-reset h2 { - font-weight: bold; - color: #FFFFFF; - /* Font is duplicated of body (sans-serif) */ - font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; - - margin-bottom: 10px; - background-color: #aacd4e; - padding: 2px 4px; - display: inline-block; - text-transform: uppercase; - -} -p { - line-height: 20px; - padding-bottom: 20px; -} -ul#demo-list a { - background: url(../images/blue-arrow.png) no-repeat right 6px; - padding-right: 10px; - margin-right: 30px; -} -#symfony-header { - position: relative; - padding: 30px 30px 20px 30px; -} -.sf-reset .symfony-blocks-welcome { - overflow: hidden; -} -.sf-reset .symfony-blocks-welcome > div { - background-color: whitesmoke; - float: left; - width: 240px; - margin-right: 14px; - text-align: center; - padding: 26px 20px; -} -.sf-reset .symfony-blocks-welcome > div.block-demo { - margin-right: 0; -} -.sf-reset .symfony-blocks-welcome .illustration { - padding-bottom: 20px; -} -.sf-reset .symfony-blocks-help { - overflow: hidden; -} -.sf-reset .symfony-blocks-help { - margin-top: 30px; - padding: 18px; - border: 1px solid #E6E6E6; -} -.sf-reset .symfony-blocks-help > div { - width: 254px; - float: left; -} -.flash-message { - padding: 10px; - margin: 5px; - margin-top: 15px; - background-color: #ffe; -} -.sf-reset .error { - color: red; -} -#login label, #contact_form label { - display: block; - float: left; - width: 90px; -} -.sf-reset ul#menu { - float: right; - margin-bottom: 20px; - padding-left: 0; -} -.sf-reset #menu li { - padding-left: 0; - margin-right: 10px; - display: inline; -} -.sf-reset a, -.sf-reset li a { - color: #08C; - text-decoration: none; -} -.sf-reset a:hover, -.sf-reset li a:hover { - color: #08C; - text-decoration: underline; -} -.sf-reset .symfony-content pre { - white-space: pre; - font-family: monospace; -} diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/blue-arrow.png b/Symfony/src/Acme/DemoBundle/Resources/public/images/blue-arrow.png deleted file mode 100644 index fa82d4b..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/blue-arrow.png and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/field-background.gif b/Symfony/src/Acme/DemoBundle/Resources/public/images/field-background.gif deleted file mode 100644 index 7c0efc1..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/field-background.gif and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/logo.gif b/Symfony/src/Acme/DemoBundle/Resources/public/images/logo.gif deleted file mode 100644 index 703cf45..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/logo.gif and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/search.png b/Symfony/src/Acme/DemoBundle/Resources/public/images/search.png deleted file mode 100644 index 3c88b6a..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/search.png and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-configure.gif b/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-configure.gif deleted file mode 100644 index 931179a..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-configure.gif and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-demo.gif b/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-demo.gif deleted file mode 100644 index 0623de5..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-demo.gif and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-quick-tour.gif b/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-quick-tour.gif deleted file mode 100644 index b9018b1..0000000 Binary files a/Symfony/src/Acme/DemoBundle/Resources/public/images/welcome-quick-tour.gif and /dev/null differ diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Demo/contact.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Demo/contact.html.twig deleted file mode 100644 index e5b7523..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Demo/contact.html.twig +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "AcmeDemoBundle::layout.html.twig" %} - -{% block title "Symfony - Contact form" %} - -{% block content %} -
- {{ form_errors(form) }} - - {{ form_row(form.email) }} - {{ form_row(form.message) }} - - {{ form_rest(form) }} - -
-{% endblock %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig deleted file mode 100644 index 3997ff6..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Demo/hello.html.twig +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "AcmeDemoBundle::layout.html.twig" %} - -{% block title "Hello " ~ name %} - -{% block content %} -

Hello {{ name }}!

-{% endblock %} - -{% set code = code(_self) %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Demo/index.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Demo/index.html.twig deleted file mode 100644 index 454a320..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Demo/index.html.twig +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "AcmeDemoBundle::layout.html.twig" %} - -{% block title "Symfony - Demos" %} - -{% block content_header '' %} - -{% block content %} -

Available demos

- -{% endblock %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/hello.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Secured/hello.html.twig deleted file mode 100644 index faf95cf..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/hello.html.twig +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "AcmeDemoBundle:Secured:layout.html.twig" %} - -{% block title "Hello " ~ name %} - -{% block content %} -

Hello {{ name }}!

- - Hello resource secured for admin only. -{% endblock %} - -{% set code = code(_self) %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/helloadmin.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Secured/helloadmin.html.twig deleted file mode 100644 index 4e3649f..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/helloadmin.html.twig +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "AcmeDemoBundle:Secured:layout.html.twig" %} - -{% block title "Hello " ~ name %} - -{% block content %} -

Hello {{ name }} secured for Admins only!

-{% endblock %} - -{% set code = code(_self) %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/layout.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Secured/layout.html.twig deleted file mode 100644 index aeea55c..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/layout.html.twig +++ /dev/null @@ -1,6 +0,0 @@ -{% extends "AcmeDemoBundle::layout.html.twig" %} - -{% block content_header_more %} - {{ parent() }} -
  • logged in as {{ app.user ? app.user.username : 'Anonymous' }} - Logout
  • -{% endblock %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/login.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Secured/login.html.twig deleted file mode 100644 index e74a5aa..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Secured/login.html.twig +++ /dev/null @@ -1,35 +0,0 @@ -{% extends 'AcmeDemoBundle::layout.html.twig' %} - -{% block content %} -

    Login

    - -

    - Choose between two default users: user/userpass (ROLE_USER) or admin/adminpass (ROLE_ADMIN) -

    - - {% if error %} -
    {{ error.message }}
    - {% endif %} - -
    -
    - - -
    - -
    - - -
    - - -
    -{% endblock %} - -{% set code = code(_self) %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig deleted file mode 100644 index ea3a729..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig +++ /dev/null @@ -1,83 +0,0 @@ -{% extends 'AcmeDemoBundle::layout.html.twig' %} - -{% block title %}Symfony - Welcome{% endblock %} - -{% block content_header '' %} - -{% block content %} - {% set version = constant('Symfony\\Component\\HttpKernel\\Kernel::MAJOR_VERSION') ~ '.' ~ constant('Symfony\\Component\\HttpKernel\\Kernel::MINOR_VERSION')%} - -

    Welcome!

    - -

    Congratulations! You have successfully installed a new Symfony application.

    - -
    -
    -
    - Quick tour -
    - - - - Read the Quick Tour - - - -
    - {% if app.environment == 'dev' %} -
    -
    - Configure your application -
    - - - - Configure - - - -
    - {% endif %} -
    -
    - Demo -
    - - - - Run The Demo - - - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -{% endblock %} diff --git a/Symfony/src/Acme/DemoBundle/Resources/views/layout.html.twig b/Symfony/src/Acme/DemoBundle/Resources/views/layout.html.twig deleted file mode 100644 index d7e97d5..0000000 --- a/Symfony/src/Acme/DemoBundle/Resources/views/layout.html.twig +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "TwigBundle::layout.html.twig" %} - -{% block head %} - - -{% endblock %} - -{% block title 'Demo Bundle' %} - -{% block body %} - {% for flashMessage in app.session.flashbag.get('notice') %} -
    - Notice: {{ flashMessage }} -
    - {% endfor %} - - {% block content_header %} - - -
    - {% endblock %} - -
    - {% block content %}{% endblock %} -
    - - {% if code is defined %} -

    Code behind this page

    -
    -
    {{ code|raw }}
    -
    - {% endif %} -{% endblock %} diff --git a/Symfony/src/Acme/DemoBundle/Tests/Controller/DemoControllerTest.php b/Symfony/src/Acme/DemoBundle/Tests/Controller/DemoControllerTest.php deleted file mode 100644 index d720ce5..0000000 --- a/Symfony/src/Acme/DemoBundle/Tests/Controller/DemoControllerTest.php +++ /dev/null @@ -1,17 +0,0 @@ -request('GET', '/demo/hello/Fabien'); -// -// $this->assertGreaterThan(0, $crawler->filter('html:contains("Hello Fabien")')->count()); -// } -//} diff --git a/Symfony/src/Acme/DemoBundle/Twig/Extension/DemoExtension.php b/Symfony/src/Acme/DemoBundle/Twig/Extension/DemoExtension.php deleted file mode 100644 index a96a885..0000000 --- a/Symfony/src/Acme/DemoBundle/Twig/Extension/DemoExtension.php +++ /dev/null @@ -1,81 +0,0 @@ -loader = $loader; - } - - public function setController($controller) - { - $this->controller = $controller; - } - - /** - * {@inheritdoc} - */ - public function getFunctions() - { - return array( - 'code' => new \Twig_Function_Method($this, 'getCode', array('is_safe' => array('html'))), - ); - } - - public function getCode($template) - { - // highlight_string highlights php code only if 'getControllerCode(), true); - $controller = str_replace('<?php    ', '    ', $controller); - - $template = htmlspecialchars($this->getTemplateCode($template), ENT_QUOTES, 'UTF-8'); - - // remove the code block - $template = str_replace('{% set code = code(_self) %}', '', $template); - - return <<Controller Code

    -
    $controller
    - -

    Template Code

    -
    $template
    -EOF; - } - - protected function getControllerCode() - { - $class = get_class($this->controller[0]); - if (class_exists('CG\Core\ClassUtils')) { - $class = ClassUtils::getUserClass($class); - } - - $r = new \ReflectionClass($class); - $m = $r->getMethod($this->controller[1]); - - $code = file($r->getFilename()); - - return ' '.$m->getDocComment()."\n".implode('', array_slice($code, $m->getStartline() - 1, $m->getEndLine() - $m->getStartline() + 1)); - } - - protected function getTemplateCode($template) - { - return $this->loader->getSource($template->getTemplateName()); - } - - /** - * Returns the name of the extension. - * - * @return string The extension name - */ - public function getName() - { - return 'demo'; - } -} diff --git a/Symfony/src/Codebender/CompilerBundle/Controller/DefaultController.php b/Symfony/src/Codebender/CompilerBundle/Controller/DefaultController.php index 15b7f3f..1b181a9 100644 --- a/Symfony/src/Codebender/CompilerBundle/Controller/DefaultController.php +++ b/Symfony/src/Codebender/CompilerBundle/Controller/DefaultController.php @@ -1,13 +1,13 @@ getRequest()->getContent(); - //Get the compiler service + //Get the compiler service + /** @var CompilerHandler $compiler */ $compiler = $this->get('compiler_handler'); $reply = $compiler->main($request, $params); @@ -69,121 +71,95 @@ public function indexAction($authorizationKey, $version) } } - public function deleteAllObjectsAction($authorizationKey, $version) - { - if ($this->container->getParameter('authorizationKey') != $authorizationKey) - return new Response(json_encode(array("success" => false, "step" => 0, "message" => "Invalid authorization key."))); - - if ($version != "v1") - return new Response(json_encode(array("success" => false, "step" => 0, "message" => "Invalid API version."))); - - $tempDir = $this->container->getParameter('temp_dir'); - $objectFilesDir = $this->container->getParameter('objdir'); - $fileCount = 0; - $undeletedFiles = ""; - $deletionStats = array("success_dot_a" => 0, - "failure_dot_a" => 0, - "success_dot_o" => 0, - "failure_dot_o" => 0, - "success_dot_d" => 0, - "failure_dot_d" => 0, - "success_dot_LOCK" => 0, - "failure_dot_LOCK" => 0); - - if ($handle = opendir("$tempDir/$objectFilesDir")) - { - - while (false !== ($entry = readdir($handle))) - { - if ($entry != "." && $entry != ".." && $entry != ".DS_Store") - { - $fileCount++; - $extension = pathinfo($entry, PATHINFO_EXTENSION); - - if (!in_array($extension, array("a", "o", "d", "LOCK"))) - continue; - - if (@unlink("$tempDir/$objectFilesDir/$entry") === false) - { - $deletionStats["failure_dot_$extension"]++; - $undeletedFiles .= $entry . "\n"; - } - else - $deletionStats["success_dot_$extension"]++; - } - } - closedir($handle); - }else - return new Response(json_encode(array("success" => false, "step" => 0, "message" => "Failed to access object files directory."))); - - return new Response(json_encode(array_merge(array("success" => true, - "message" => "Object files deletion complete. Found $fileCount files."), - $deletionStats, - array("Files not deleted" => $undeletedFiles)))); - } + public function deleteAllObjectsAction($authorizationKey, $version) + { + if ($this->container->getParameter('authorizationKey') != $authorizationKey) { + return new Response(json_encode( + array('success' => false, 'step' => 0, 'message' => 'Invalid authorization key.') + )); + } - public function deleteSpecificObjectsAction($authorizationKey, $version, $option, $to_delete) - { - if ($this->container->getParameter('authorizationKey') != $authorizationKey) - return new Response(json_encode(array("success" => false, "step" => 0, "message" => "Invalid authorization key."))); + if ($version != 'v1') { + return new Response(json_encode( + array('success' => false, 'step' => 0, 'message' => 'Invalid API version.') + )); + } - if ($version != "v1") - return new Response(json_encode(array("success" => false, "step" => 0, "message" => "Invalid API version."))); + //Get the compiler service + /** @var DeletionHandler $deleter */ + $deleter = $this->get('deletion_handler'); - $tempDir = $this->container->getParameter('temp_dir'); - $objectFilesDir = $this->container->getParameter('objdir'); + $response = $deleter->deleteAllObjects(); - if ($option == "core") - $to_delete = str_replace(":", "_", $to_delete); + if ($response['success'] !== true) { + return new Response(json_encode( + array('success' => false, 'step' => 0, 'message' => 'Failed to access object files directory.') + )); + } - $response = array(); - $response["deleted_files"] = ""; - $response["undeleted_files"] = ""; + return new Response(json_encode( + array_merge( + array( + 'success' => true, + 'message' => 'Object files deletion complete. Found ' . $response['fileCount'] . ' files.' + ), + $response['deletionStats'], + array("Files not deleted" => $response['notDeletedFiles']) + ))); + } - if ($handle = opendir("$tempDir/$objectFilesDir")) - { - while (false !== ($entry = readdir($handle))) - { - if ($entry == "." || $entry == ".." || $entry == ".DS_Store") - continue; + public function deleteSpecificObjectsAction($authorizationKey, $version, $option, $cachedObjectToDelete) + { + if ($this->container->getParameter('authorizationKey') != $authorizationKey) { + return new Response(json_encode( + array('success' => false, 'step' => 0, 'message' => 'Invalid authorization key.') + )); + } - if ($option == "library" && strpos($entry, "______" . $to_delete . "_______") === false) - continue; + if ($version != 'v1') { + return new Response(json_encode( + array('success' => false, 'step' => 0, 'message' => 'Invalid API version.') + )); + } - if ($option == "core" && strpos($entry, "_" . $to_delete . "_") === false) - continue; + //Get the compiler service + /** @var DeletionHandler $deleter */ + $deleter = $this->get('deletion_handler'); + $response = $deleter->deleteSpecificObjects($option, $cachedObjectToDelete); - if (@unlink("$tempDir/$objectFilesDir/$entry") === false) - $response["undeleted_files"] .= $entry . "\n"; - else - $response["deleted_files"] .= $entry . "\n"; + if ($response['success'] !== true) { + return new Response(json_encode( + array('success' => false, 'step' => 0, 'message' => 'Failed to access object files directory.') + )); + } + if (!empty($response["notDeletedFiles"])) { + $message = 'Failed to delete one or more of the specified core object files.'; + if ($option == 'library') { + $message = 'Failed to delete one or more of the specified library object files.'; } - closedir($handle); - } - else - { - return new Response(json_encode(array("success" => false, "step" => 0, "message" => "Failed to access object files directory."))); - } - if ($response["undeleted_files"] != "") - { - $message = ($option == "library") ? "Failed to delete one or more of the specified library object files.": "Failed to delete one or more of the specified core object files."; - return new Response(json_encode(array_merge(array("success" => false, "step" => 0, "message" => $message), $response))); + return new Response(json_encode( + array_merge(array('success' => false, 'step' => 0, 'message' => $message), $response) + )); + } + + $message = 'Core object files deleted successfully.'; + if ($option == 'library'){ + $message = 'Library deleted successfully.'; } - $message = ($option == "library") ? "Library deleted successfully.": "Core object files deleted successfully."; - return new Response(json_encode(array_merge(array("success" => true, "message" => $message), $response))); - } + return new Response(json_encode(array_merge(array('success' => true, 'message' => $message), $response))); + } /** - \brief Creates a list of the configuration parameters to be used in the compilation process. - - \return An array of the parameters. - - This function accesses the Symfony global configuration parameters, and creates an array that our handlers (which - don't have access to them) can use them. + * \brief Creates a list of the configuration parameters to be used in the compilation process. + * + * \return An array of the parameters. + * + * This function accesses the Symfony global configuration parameters, and creates an array that our handlers (which + * don't have access to them) can use them. */ private function generateParameters() diff --git a/Symfony/src/Codebender/CompilerBundle/Handler/CompilerHandler.php b/Symfony/src/Codebender/CompilerBundle/Handler/CompilerHandler.php index 7907186..5a1a394 100644 --- a/Symfony/src/Codebender/CompilerBundle/Handler/CompilerHandler.php +++ b/Symfony/src/Codebender/CompilerBundle/Handler/CompilerHandler.php @@ -1,13 +1,13 @@ preproc = $preprocHandl; - $this->postproc = $postprocHandl; - $this->utility = $utilHandl; - $this->compiler_logger = $logger; - $this->object_directory = $objdir; - } - - /** - \brief Processes a compile request. - - \param string $request The body of the POST request. - \return A message to be JSON-encoded and sent back to the requestor. - */ - function main($request, $compiler_config) - { - error_reporting(E_ALL & ~E_STRICT); - - $this->set_values($compiler_config, - $BINUTILS, $CLANG, $CFLAGS, $CPPFLAGS, $ASFLAGS, $ARFLAGS, $LDFLAGS, $LDFLAGS_TAIL, - $CLANG_FLAGS, $OBJCOPY_FLAGS, $SIZE_FLAGS, $OUTPUT, $ARDUINO_CORES_DIR, $EXTERNAL_CORES_DIR, + private $preproc; + private $postproc; + private $utility; + private $compiler_logger; + private $object_directory; + private $logger_id; + + function __construct(PreprocessingHandler $preprocHandl, PostprocessingHandler $postprocHandl, UtilityHandler $utilHandl, Logger $logger, $objdir) + { + $this->preproc = $preprocHandl; + $this->postproc = $postprocHandl; + $this->utility = $utilHandl; + $this->compiler_logger = $logger; + $this->object_directory = $objdir; + } + + /** + * \brief Processes a compile request. + * + * \param string $request The body of the POST request. + * \return A message to be JSON-encoded and sent back to the requestor. + */ + function main($request, $compiler_config) + { + error_reporting(E_ALL & ~E_STRICT); + + $this->setValues($compiler_config, + $BINUTILS, $CLANG, $CFLAGS, $CPPFLAGS, $ASFLAGS, $ARFLAGS, $LDFLAGS, $LDFLAGS_TAIL, + $CLANG_FLAGS, $OBJCOPY_FLAGS, $SIZE_FLAGS, $OUTPUT, $ARDUINO_CORES_DIR, $EXTERNAL_CORES_DIR, $TEMP_DIR, $ARCHIVE_DIR, $AUTOCC_DIR, $PYTHON, $AUTOCOMPLETER); - $start_time = microtime(true); + $start_time = microtime(true); - // Step 0: Reject the request if the input data is not valid. - //TODO: Replace $tmp variable name - $tmp = $this->requestValid($request); - if($tmp["success"] === false) - return $tmp; + // Step 0: Reject the request if the input data is not valid. + $tmpVar = $this->requestValid($request); + if ($tmpVar["success"] === false) + return $tmpVar; - $this->set_variables($request, $format, $libraries, $version, $mcu, $f_cpu, $core, $variant, $vid, $pid, $compiler_config); + $this->setVariables($request, $format, $libraries, $version, $mcu, $f_cpu, $core, $variant, $vid, $pid, $compiler_config); - $this->set_avr($version, $ARDUINO_CORES_DIR, $BINUTILS, $CC, $CPP, $AS, $AR, $LD, $OBJCOPY, $SIZE); + $this->setAVR($version, $ARDUINO_CORES_DIR, $BINUTILS, $CC, $CPP, $AS, $AR, $LD, $OBJCOPY, $SIZE); - $target_arch = "-mmcu=$mcu -DARDUINO=$version -DF_CPU=$f_cpu -DUSB_VID=$vid -DUSB_PID=$pid"; - $clang_target_arch = "-D".MCUHandler::$MCU[$mcu]." -DARDUINO=$version -DF_CPU=$f_cpu"; + $target_arch = "-mmcu=$mcu -DARDUINO=$version -DF_CPU=$f_cpu -DUSB_VID=$vid -DUSB_PID=$pid"; + $clang_target_arch = "-D".MCUHandler::$MCU[$mcu]." -DARDUINO=$version -DF_CPU=$f_cpu"; $autocc_clang_target_arch = "-D".MCUHandler::$MCU[$mcu]." -DARDUINO=$version -DF_CPU=$f_cpu -DUSB_VID=$vid -DUSB_PID=$pid"; - // Step 1(part 1): Extract the project files included in the request. - $files = array(); - $tmp = $this->extractFiles($request["files"], $TEMP_DIR, $compiler_dir, $files["sketch_files"], "files"); - - if ($tmp["success"] == false) - return $tmp; - - // Add the compiler temp directory to the compiler_config struct. - $compiler_config["compiler_dir"] = $compiler_dir; - - // Step 1(part 2): Extract the library files included in the request. - $files["libs"] = array(); - foreach($libraries as $library => $library_files){ - - $tmp = $this->extractFiles($library_files, $TEMP_DIR, $compiler_dir, $files["libs"][$library], "libraries/$library", true); - if ($tmp["success"] == false) - return $tmp; - } - - if (!array_key_exists("archive", $request) || ($request["archive"] !== false && $request["archive"] !== true)) - $ARCHIVE_OPTION = false; - else - $ARCHIVE_OPTION = $request["archive"]; - //return array("success" => false, "archive option" => $ARCHIVE_OPTION); - if ($ARCHIVE_OPTION === true){ - $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); - if ($arch_ret["success"] === false) - return $arch_ret; - } - - //Set logging to true if requested, and create the directory where logfiles are stored. - //TODO: Replace $tmp variable name - $tmp = $this->setLoggingParams($request, $compiler_config, $TEMP_DIR, $compiler_dir); - if($tmp["success"] === false) - return array_merge($tmp, ($ARCHIVE_OPTION ===true) ? array("archive" => $ARCHIVE_PATH) : array()); - - // Step 2: Preprocess Arduino source files. - $tmp = $this->preprocessIno($files["sketch_files"]); - if ($tmp["success"] == false) - return array_merge($tmp, ($ARCHIVE_OPTION ===true) ? array("archive" => $ARCHIVE_PATH) : array()); - - // Step 3: Preprocess Header includes and determine which core files directory(CORE_DIR) will be used. - $tmp = $this->preprocessHeaders($libraries, $include_directories, $compiler_dir, $ARDUINO_CORES_DIR, $EXTERNAL_CORES_DIR, $CORE_DIR, $CORE_OVERRIDE_DIR, $version, $core, $variant); - if ($tmp["success"] == false) - return array_merge($tmp, ($ARCHIVE_OPTION ===true) ? array("archive" => $ARCHIVE_PATH) : array()); - - // Log the names of the project files and the libraries used in it. - if ($format != "autocomplete") { - $req_elements = array("Files: "); - - foreach ($request["files"] as $file) { - $req_elements[] = $file["filename"]; - if (strpos($file["filename"], ".txt") !== false) { - if (preg_match('/(?<=user_)[\d]+/', $file['filename'], $match)) $user_id = $match[0]; - if (preg_match('/(?<=project_)[\d]+/', $file['filename'], $match)) $sketch_id = $match[0]; - - } - } - - if ($request["libraries"]) { - $req_elements[] = "Libraries: "; - foreach ($request["libraries"] as $libname => $libfiles) { - foreach ($libfiles as $libfile) - $req_elements[] = $libname . "/" . $libfile["filename"]; - } - } - - $user_id = "null"; - if (isset($request['userId'])) { - $user_id = $request['userId']; - } - - $sketch_id = "null"; - if (isset($request['projectId'])) { - $sketch_id = $request['projectId']; - } - - $this->logger_id = microtime(true) . "_" . substr($compiler_config['compiler_dir'], -6) . "_user:$user_id" . "_project:$sketch_id"; - - $this->compiler_logger->addInfo($this->logger_id . " - " . implode(" ", $req_elements)); - if ($ARCHIVE_OPTION === true) - $this->compiler_logger->addInfo($this->logger_id . " - " . "Archive file: $ARCHIVE_PATH"); - } - - // Step 4: Syntax-check and compile source files. - //Use the include paths for the AVR headers that are bundled with each Arduino SDK version - //These may differ between linux and MAC OS versions of the Arduino core files, so check before including - $core_includes = ""; - if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include")) - $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include"; - if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include-fixed")) - $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include-fixed"; - if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/avr/include")) - $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/avr/include "; - elseif (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/avr/include")) - $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/avr/include "; - - if ($format == "autocomplete"){ + // Step 1(part 1): Extract the project files included in the request. + $files = array(); + $tmpVar = $this->extractFiles($request["files"], $TEMP_DIR, $compiler_dir, $files["sketch_files"], "files"); + + if ($tmpVar["success"] === false) + return $tmpVar; + + // Add the compiler temp directory to the compiler_config struct. + $compiler_config["compiler_dir"] = $compiler_dir; + + // Step 1(part 2): Extract the library files included in the request. + $files["libs"] = array(); + foreach ($libraries as $library => $library_files) + { + + $tmpVar = $this->extractFiles($library_files, $TEMP_DIR, $compiler_dir, $files["libs"][$library], "libraries/$library", true); + if ($tmpVar["success"] === false) + return $tmpVar; + } + + if (!array_key_exists("archive", $request) || ($request["archive"] !== false && $request["archive"] !== true)) + $ARCHIVE_OPTION = false; + else + $ARCHIVE_OPTION = $request["archive"]; + + if ($ARCHIVE_OPTION === true) + { + $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); + if ($arch_ret["success"] === false) + return $arch_ret; + } + + //Set logging to true if requested, and create the directory where logfiles are stored. + $tmpVar = $this->setLoggingParams($request, $compiler_config, $TEMP_DIR, $compiler_dir); + if ($tmpVar["success"] === false) + return array_merge($tmpVar, ($ARCHIVE_OPTION === true) ? array("archive" => $ARCHIVE_PATH) : array()); + + // Step 2: Preprocess Arduino source files. + $tmpVar = $this->preprocessIno($files["sketch_files"]); + if ($tmpVar["success"] === false) + return array_merge($tmpVar, ($ARCHIVE_OPTION === true) ? array("archive" => $ARCHIVE_PATH) : array()); + + // Step 3: Preprocess Header includes and determine which core files directory(CORE_DIR) will be used. + $tmpVar = $this->preprocessHeaders($libraries, $include_directories, $compiler_dir, $ARDUINO_CORES_DIR, $EXTERNAL_CORES_DIR, $CORE_DIR, $CORE_OVERRIDE_DIR, $version, $core, $variant); + if ($tmpVar["success"] === false) + return array_merge($tmpVar, ($ARCHIVE_OPTION === true) ? array("archive" => $ARCHIVE_PATH) : array()); + + // Log the names of the project files and the libraries used in it. + if ($format != "autocomplete") + { + $user_id = $sketch_id = "null"; + $req_elements = array("Files: "); + + foreach ($request["files"] as $file) + { + $req_elements[] = $file["filename"]; + if (strpos($file["filename"], ".txt") !== false) + { + if (preg_match('/(?<=user_)[\d]+/', $file['filename'], $match)) $user_id = $match[0]; + if (preg_match('/(?<=project_)[\d]+/', $file['filename'], $match)) $sketch_id = $match[0]; + + } + } + + if ($request["libraries"]) + { + $req_elements[] = "Libraries: "; + foreach ($request["libraries"] as $libname => $libfiles) + { + foreach ($libfiles as $libfile) + $req_elements[] = $libname."/".$libfile["filename"]; + } + } + + $this->logger_id = microtime(true)."_".substr($compiler_config['compiler_dir'], -6)."_user:$user_id"."_project:$sketch_id"; + + $this->compiler_logger->addInfo($this->logger_id." - ".implode(" ", $req_elements)); + if ($ARCHIVE_OPTION === true) + $this->compiler_logger->addInfo($this->logger_id." - "."Archive file: $ARCHIVE_PATH"); + } + + // Step 4: Syntax-check and compile source files. + //Use the include paths for the AVR headers that are bundled with each Arduino SDK version + //These may differ between linux and MAC OS versions of the Arduino core files, so check before including + $core_includes = ""; + if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include")) + $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include"; + if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include-fixed")) + $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/gcc/avr/4.3.2/include-fixed"; + if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/avr/include")) + $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/avr/include "; + elseif (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/avr/include")) + $core_includes .= " -I$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/lib/avr/include "; + + if ($format == "autocomplete") + { $autocompleteRet = $this->handleAutocompletion($ARDUINO_CORES_DIR, "$compiler_dir/files", $include_directories["main"], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $core_includes, $autocc_clang_target_arch, $TEMP_DIR, $AUTOCC_DIR, $PYTHON, $AUTOCOMPLETER); - if ($ARCHIVE_OPTION === true){ + if ($ARCHIVE_OPTION === true) + { $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); if ($arch_ret["success"] === false) return $arch_ret; @@ -177,855 +174,968 @@ function main($request, $compiler_config) return array_merge($autocompleteRet, array("total_compiler_exec_time" => microtime(true) - $start_time)); } - //handleCompile sets any include directories needed and calls the doCompile function, which does the actual compilation - $ret = $this->handleCompile("$compiler_dir/files", $files["sketch_files"], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories["main"], $format); - - $log_content = (($compiler_config['logging'] === true) ? @file_get_contents($compiler_config['logFileName']) : ""); - if ($compiler_config['logging'] === true){ - if ($log_content !== false) { - $ret["log"] = $log_content; - file_put_contents($compiler_config["compiler_dir"] . "/log", $log_content); - } - else - $ret["log"] = "Failed to access logfile."; - } - - if ($ARCHIVE_OPTION === true){ - $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); - if ($arch_ret["success"] === false) - $ret["archive"] = $arch_ret["message"]; - else - $ret["archive"] = $ARCHIVE_PATH; - } - - if (!$ret["success"]) - return $ret; - - if ($format == "syntax") - return array_merge(array( - "success" => true, - "time" => microtime(true) - $start_time), - ($ARCHIVE_OPTION ===true) ? array("archive" => $ret["archive"]) : array(), - ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); - - //Keep all object files urls needed for linking. - $objects_to_link = $files["sketch_files"]["o"]; - - //TODO: return objects if more than one file?? - if ($format == "object") - { - $content = base64_encode(file_get_contents($files["sketch_files"]["o"][0].".o")); - if (count($files["sketch_files"]["o"]) != 1 || !$content){ - return array_merge(array( - "success" => false, - "step" => -1, //TODO: Fix this step? - "message" => ""), - ($ARCHIVE_OPTION ===true) ? array("archive" => $ret["archive"]) : array(), - ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); - } - else - return array_merge(array( - "success" => true, - "time" => microtime(true) - $start_time, - "output" => $content), - ($ARCHIVE_OPTION ===true) ? array("archive" => $ret["archive"]) : array(), - ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); - } - - // Step 5: Create objects for core files (if core file does not already exist) - //Link all core object files to a core.a library. - - //TODO: Figure out why Symfony needs "@" to suppress mkdir wanring - if(!file_exists($this->object_directory)){ - //The code below was added to ensure that no error will be returned because of multithreaded execution. - $make_dir_success = @mkdir($this->object_directory, 0777, true); - if (!$make_dir_success && !is_dir($this->object_directory)) { - usleep(rand( 5000 , 10000 )); - $make_dir_success = @mkdir($this->object_directory, 0777, true); - } - if(!$make_dir_success){ - return array_merge(array( - "success" => false, - "step" => 5, - "message" => "Could not create object files directory."), - ($ARCHIVE_OPTION ===true) ? array("archive" => $ret["archive"]) : array(), - ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); - } - } - - //Generate full pathname of the cores library and then check if the library exists. - $core_library = $this->object_directory ."/". pathinfo(str_replace("/", "__", $CORE_DIR."_"), PATHINFO_FILENAME)."_______"."${mcu}_${f_cpu}_${core}_${variant}_${vid}_${pid}_______"."core.a"; - - $lock = fopen("$core_library.LOCK", "w"); - - flock($lock, LOCK_EX); - if (!file_exists($core_library)){ - //makeCoresTmp scans the core files directory and return list including the urls of the files included there. - $tmp = $this->makeCoresTmp($CORE_DIR, $CORE_OVERRIDE_DIR, $TEMP_DIR, $compiler_dir, $files); - - if(!$tmp["success"]){ - return array_merge($tmp, - ($ARCHIVE_OPTION ===true) ? array("archive" => $ret["archive"]) : array(), - ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); - } - - $ret = $this->handleCompile("$compiler_dir/core", $files["core"], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories["core"], "object"); - - $log_content = (($compiler_config['logging'] === true) ? @file_get_contents($compiler_config['logFileName']) : ""); - - if ($compiler_config['logging'] === true){ - if ($log_content !== false){ - $ret["log"] = $log_content; - file_put_contents($compiler_config["compiler_dir"] . "/log", $log_content); - } - else - $ret["log"] = "Failed to access logfile."; - } - - if ($ARCHIVE_OPTION === true){ - $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); - if ($arch_ret["success"] === false) - $ret["archive"] = $arch_ret["message"]; - else - $ret["archive"] = $ARCHIVE_PATH; - } - - if (!$ret["success"]) - return $ret; - - foreach ($files["core"]["o"] as $core_object){ - //Link object file to library. - exec("$AR $ARFLAGS $core_library $core_object.o", $output); - - if ($compiler_config['logging']) - file_put_contents($compiler_config['logFileName'], "$AR $ARFLAGS $core_library $core_object.o"."\n", FILE_APPEND); - } - flock($lock, LOCK_UN); - fclose($lock); - } - else{ - flock($lock, LOCK_UN); - fclose($lock); - if($compiler_config['logging']) - file_put_contents($compiler_config['logFileName'],"\nUsing previously compiled version of $core_library\n", FILE_APPEND); - } - - // Step 6: Create objects for libraries. - // The elements of the "build" array are needed to build the unique name of every library object file. - $lib_object_naming_params = $request["build"]; - if (!array_key_exists("variant", $request["build"])) - $lib_object_naming_params["variant"] = ""; - $lib_object_naming_params["vid"] = $vid; - $lib_object_naming_params["pid"] = $pid; - - foreach ($files["libs"] as $library_name => $library_files){ - - $lib_object_naming_params["library"] = $library_name; - - $ret = $this->handleCompile("$compiler_dir/libraries/$library_name", $files["libs"][$library_name], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories["main"], $format, true, $lib_object_naming_params); - - $log_content = (($compiler_config['logging'] === true) ? @file_get_contents($compiler_config['logFileName']) : ""); - if ($compiler_config['logging'] === true){ - if ($log_content !== false) { - $ret["log"] = $log_content; - file_put_contents($compiler_config["compiler_dir"] . "/log", $log_content); - } - else - $ret["log"] = "Failed to access logfile."; - } - - if ($ARCHIVE_OPTION === true){ - $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); - if ($arch_ret["success"] === false) - $ret["archive"] = $arch_ret["message"]; - else - $ret["archive"] = $ARCHIVE_PATH; - } - - if(!$ret["success"]) - return $ret; - - $objects_to_link = array_merge($objects_to_link, $files["libs"][$library_name]["o"]); - } - - // Step 7: Link all object files and create executable. - $object_files = ""; - foreach ($objects_to_link as $object) - $object_files .= " ".escapeshellarg("$object.o"); - - //Link core.a and every other object file to a .elf binary file - exec("$LD $LDFLAGS $target_arch $object_files $core_library -o $compiler_dir/files/$OUTPUT.elf $LDFLAGS_TAIL 2>&1", $output, $ret_link); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'], "$LD $LDFLAGS $target_arch $object_files $core_library -o $compiler_dir/files/$OUTPUT.elf $LDFLAGS_TAIL\n", FILE_APPEND); - } - - if ($ret_link){ - - // Log the fact that an error occurred during linking - $this->compiler_logger->addInfo($this->logger_id . " - An error occurred during linking: " . json_encode(implode("\n", $output))); - - $returner = array( - "success" => false, - "step" => 7, - "message" => implode("\n", $output)); - - if ($compiler_config['logging'] === true) { - $log_content = @file_get_contents($compiler_config['logFileName']); - if (!$log_content) - $returner["log"] = "Failed to access logfile."; - else { - file_put_contents($compiler_config["compiler_dir"] . "/log", $log_content); - $returner["log"] = $log_content; - } - } - - if ($ARCHIVE_OPTION === true){ - $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); - if ($arch_ret["success"] === false) - $returner["archive"] = $arch_ret["message"]; - else - $returner["archive"] = $ARCHIVE_PATH; - } - return $returner; - } - - // Step 8: Convert the output to the requested format and measure its - // size. - $tmp = $this->convertOutput("$compiler_dir/files", $format, $SIZE, $SIZE_FLAGS, $OBJCOPY, $OBJCOPY_FLAGS, $OUTPUT, $start_time, $compiler_config); - - if ($compiler_config['logging'] === true) { - $log_content = @file_get_contents($compiler_config['logFileName']); - if (!$log_content) - $tmp["log"] = "Failed to access logfile."; - else { - file_put_contents($compiler_config["compiler_dir"] . "/log", $log_content); - $tmp["log"] = $log_content; - } - } - - if ($ARCHIVE_OPTION === true){ - $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); - if ($arch_ret["success"] === false) - $tmp["archive"] = $arch_ret["message"]; - else - $tmp["archive"] = $ARCHIVE_PATH; - } - return $tmp; - } - - private function requestValid(&$request) - { - $request = $this->preproc->validate_input($request); - if (!$request) - return array( - "success" => false, - "step" => 0, - "message" => "Invalid input."); - else return array("success" => true); - } - - private function createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, &$ARCHIVE_PATH) - { - if (!file_exists($ARCHIVE_PATH)){ - // Create a directory in tmp folder and store archive files there - if (!file_exists("$TEMP_DIR/$ARCHIVE_DIR")){ - //The code below was added to ensure that no error will be returned because of multithreaded execution. - $make_dir_success = @mkdir("$TEMP_DIR/$ARCHIVE_DIR", 0777, true); - if (!$make_dir_success && !is_dir("$TEMP_DIR/$ARCHIVE_DIR")) { - usleep(rand( 5000 , 10000 )); - $make_dir_success = @mkdir("$TEMP_DIR/$ARCHIVE_DIR", 0777, true); - } - if (!$make_dir_success) - return array("success" => false, "message" => "Failed to create archive directory."); - } - - do{ - $tar_random_name = uniqid(rand(), true) . '.tar.gz'; - }while (file_exists("$TEMP_DIR/$ARCHIVE_DIR/$tar_random_name")); - $ARCHIVE_PATH = "$TEMP_DIR/$ARCHIVE_DIR/$tar_random_name"; - } - - // The archive files include all the files of the project and the libraries needed to compile it - exec("tar -zcvf $ARCHIVE_PATH -C $TEMP_DIR/ ". pathinfo($compiler_dir, PATHINFO_BASENAME), $output, $ret_var); - - if ($ret_var !=0) - return array("success" => false, "message" => "Failed to archive project files."); - return array("success" => true); - } - - private function extractFiles($request, $temp_dir, &$dir, &$files, $suffix, $lib_extraction = false) - { - // Create a temporary directory to place all the files needed to process - // the compile request. This directory is created in $TMPDIR or /tmp by - // default and is automatically removed upon execution completion. - $cnt = 0; - if (!$dir) - do { - $dir = @System::mktemp("-t $temp_dir/ -d compiler."); - $cnt++; - } while (!$dir && $cnt <= 2); - - if (!$dir) - return array( - "success" => false, - "step" => 1, - "message" => "Failed to create temporary directory."); - - $response = $this->utility->extract_files("$dir/$suffix", $request, $lib_extraction); - - if ($response["success"] === false) - return $response; - $files = $response["files"]; - - return array("success" => true); - } - - private function preprocessIno(&$files) - { - foreach ($files["ino"] as $file) - { - $code = file_get_contents("$file.ino"); - $new_code = $this->preproc->ino_to_cpp($code, "$file.ino"); - $ret = file_put_contents("$file.cpp", $new_code); - - if ($code === false || !$new_code || !$ret) - return array( - "success" => false, - "step" => 2, - "message" => "Failed to preprocess file '$file.ino'."); - - $files["cpp"][] = array_shift($files["ino"]); - } - - return array("success" => true); - } - - public function preprocessHeaders($libraries, &$include_directories, $dir, $ARDUINO_CORES_DIR, $EXTERNAL_CORES_DIR, &$CORE_DIR, &$CORE_OVERRIDE_DIR, $version, &$core, &$variant) - { - try - { - // Create command-line arguments for header search paths. Note that the - // current directory is added to eliminate the difference between <> - // and "" in include preprocessor directives. - - // Check if the core or variant contains a semicolon. - // When a semicolon exists both the core folder and the core itself are specified. - // The same applies to the variant specification. - - $core_specs = array('folder' => "arduino", 'name' => $core, 'modified' => false); - $variant_specs = array('folder' => "arduino", 'name' => $variant, 'modified' => false); - - $tmp = explode(":", $core); - if (count($tmp) == 2){ - $core_specs = array('folder' => $tmp[0], 'name' => $tmp[1], 'modified' => true); - $core = str_replace(":", "_", $core); //core name is used for object file naming, so it shouldn't contain any semicolons - } - elseif (count($tmp) != 1) - return array("success" => false, "step" => 3, "message" => "Invalid core specifier."); - - $tmp = explode(":", $variant); - if (count($tmp) == 2){ - $variant_specs = array('folder' => $tmp[0], 'name' => $tmp[1], 'modified' => true); - $variant = str_replace(":", "_", $variant); //variant name is used for object file naming, so it shouldn't contain any semicolons - } - elseif (count($tmp) != 1) - return array("success" => false, "step" => 3, "message" => "Invalid variant specifier."); - - - - $include_directories = array(); - - // Try to locate the core files - if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/".$core_specs['folder']."/cores/".$core_specs['name'])){ - $CORE_DIR = "$ARDUINO_CORES_DIR/v$version/hardware/".$core_specs['folder']."/cores/".$core_specs['name']; - } - elseif (is_dir($EXTERNAL_CORES_DIR)){ - if ($core_specs['modified'] === true){ - if (file_exists("$EXTERNAL_CORES_DIR/".$core_specs['folder']."/cores/".$core_specs['name'])) - $CORE_DIR = "$EXTERNAL_CORES_DIR/".$core_specs['folder']."/cores/".$core_specs['name']; - } - elseif (false !== ($externals = @scandir($EXTERNAL_CORES_DIR))){ - foreach ($externals as $dirname) - if (is_dir("$EXTERNAL_CORES_DIR/$dirname/") && $dirname != "." && $dirname != ".." && file_exists("$EXTERNAL_CORES_DIR/$dirname/cores/".$core_specs['name'])){ - $CORE_DIR = "$EXTERNAL_CORES_DIR/$dirname/cores/".$core_specs['name']; - break; - } - } - } - - if (empty($CORE_DIR)) - return array("success" => false, "step" => 3, "message" => "Failed to detect core files."); - - // Try to locate the variant - if ($variant != ""){ - if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/".$variant_specs['folder']."/variants/".$variant_specs['name'])) - $variant_dir = "$ARDUINO_CORES_DIR/v$version/hardware/".$variant_specs['folder']."/variants/".$variant_specs['name']; - else { - if (is_dir($EXTERNAL_CORES_DIR)){ - if ($variant_specs['modified'] === true){ - if (file_exists("$EXTERNAL_CORES_DIR/".$variant_specs['folder']."/variants/".$variant_specs['name'])) - $variant_dir = "$EXTERNAL_CORES_DIR/".$variant_specs['folder']."/variants/".$variant_specs['name']; - } - elseif (false !== ($externals = @scandir($EXTERNAL_CORES_DIR))){ - foreach ($externals as $dirname) - if (is_dir("$EXTERNAL_CORES_DIR/$dirname") && $dirname != "." && $dirname != "..") - if ($variant != "" && file_exists("$EXTERNAL_CORES_DIR/$dirname/variants/".$variant_specs['name'])){ - $variant_dir = "$EXTERNAL_CORES_DIR/$dirname/variants/".$variant_specs['name']; - break; - } - } - } - } - } - - if (!empty($variant) && empty($variant_dir)) - return array("success" => false, "step" => 3, "message" => "Failed to detect variant."); + //handleCompile sets any include directories needed and calls the doCompile function, which does the actual compilation + $ret = $this->handleCompile("$compiler_dir/files", $files["sketch_files"], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories["main"], $format); + + $log_content = (($compiler_config['logging'] === true) ? @file_get_contents($compiler_config['logFileName']) : ""); + if ($compiler_config['logging'] === true) + { + if ($log_content !== false) + { + $ret["log"] = $log_content; + file_put_contents($compiler_config["compiler_dir"]."/log", $log_content); + } + else + $ret["log"] = "Failed to access logfile."; + } + + if ($ARCHIVE_OPTION === true) + { + $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); + if ($arch_ret["success"] === false) + $ret["archive"] = $arch_ret["message"]; + else + $ret["archive"] = $ARCHIVE_PATH; + } + + if (!$ret["success"]) + return $ret; + + if ($format == "syntax") + return array_merge(array( + "success" => true, + "time" => microtime(true) - $start_time), + ($ARCHIVE_OPTION === true) ? array("archive" => $ret["archive"]) : array(), + ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); + + //Keep all object files urls needed for linking. + $objects_to_link = $files["sketch_files"]["o"]; + + //TODO: return objects if more than one file?? + if ($format == "object") + { + $content = base64_encode(file_get_contents($files["sketch_files"]["o"][0].".o")); + if (count($files["sketch_files"]["o"]) != 1 || !$content) + { + return array_merge(array( + "success" => false, + "step" => -1, //TODO: Fix this step? + "message" => ""), + ($ARCHIVE_OPTION === true) ? array("archive" => $ret["archive"]) : array(), + ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); + } + else + return array_merge(array( + "success" => true, + "time" => microtime(true) - $start_time, + "output" => $content), + ($ARCHIVE_OPTION === true) ? array("archive" => $ret["archive"]) : array(), + ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); + } + + // Step 5: Create objects for core files (if core file does not already exist) + //Link all core object files to a core.a library. + + //TODO: Figure out why Symfony needs "@" to suppress mkdir wanring + if (!file_exists($this->object_directory)) + { + //The code below was added to ensure that no error will be returned because of multithreaded execution. + $make_dir_success = @mkdir($this->object_directory, 0777, true); + if (!$make_dir_success && !is_dir($this->object_directory)) + { + usleep(rand(5000, 10000)); + $make_dir_success = @mkdir($this->object_directory, 0777, true); + } + if (!$make_dir_success) + { + return array_merge(array( + "success" => false, + "step" => 5, + "message" => "Could not create object files directory."), + ($ARCHIVE_OPTION === true) ? array("archive" => $ret["archive"]) : array(), + ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); + } + } + + //Generate full pathname of the cores library and then check if the library exists. + $core_library = $this->object_directory."/".pathinfo(str_replace("/", "__", $CORE_DIR."_"), PATHINFO_FILENAME)."_______"."${mcu}_${f_cpu}_${core}_${variant}_${vid}_${pid}_______"."core.a"; + + $lock = fopen("$core_library.LOCK", "w"); + + flock($lock, LOCK_EX); + if (!file_exists($core_library)) + { + //makeCoresTmp scans the core files directory and return list including the urls of the files included there. + $tmpVar = $this->makeCoresTmp($CORE_DIR, $CORE_OVERRIDE_DIR, $TEMP_DIR, $compiler_dir, $files); + + if (!$tmpVar["success"]) + { + return array_merge($tmpVar, + ($ARCHIVE_OPTION === true) ? array("archive" => $ret["archive"]) : array(), + ($compiler_config['logging'] === true) ? array("log" => $ret["log"]) : array()); + } + + $ret = $this->handleCompile("$compiler_dir/core", $files["core"], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories["core"], "object"); + + $log_content = (($compiler_config['logging'] === true) ? @file_get_contents($compiler_config['logFileName']) : ""); + + if ($compiler_config['logging'] === true) + { + if ($log_content !== false) + { + $ret["log"] = $log_content; + file_put_contents($compiler_config["compiler_dir"]."/log", $log_content); + } + else + $ret["log"] = "Failed to access logfile."; + } + + if ($ARCHIVE_OPTION === true) + { + $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); + if ($arch_ret["success"] === false) + $ret["archive"] = $arch_ret["message"]; + else + $ret["archive"] = $ARCHIVE_PATH; + } + + if (!$ret["success"]) + return $ret; + + foreach ($files["core"]["o"] as $core_object) + { + //Link object file to library. + exec("$AR $ARFLAGS $core_library $core_object.o", $output); + + if ($compiler_config['logging']) + file_put_contents($compiler_config['logFileName'], "$AR $ARFLAGS $core_library $core_object.o"."\n", FILE_APPEND); + } + flock($lock, LOCK_UN); + fclose($lock); + } + else + { + flock($lock, LOCK_UN); + fclose($lock); + if ($compiler_config['logging']) + file_put_contents($compiler_config['logFileName'], "\nUsing previously compiled version of $core_library\n", FILE_APPEND); + } + + // Step 6: Create objects for libraries. + // The elements of the "build" array are needed to build the unique name of every library object file. + $lib_object_naming_params = $request["build"]; + if (!array_key_exists("variant", $request["build"])) + $lib_object_naming_params["variant"] = ""; + $lib_object_naming_params["vid"] = $vid; + $lib_object_naming_params["pid"] = $pid; + + foreach ($files["libs"] as $library_name => $library_files) + { + + $lib_object_naming_params["library"] = $library_name; + + $ret = $this->handleCompile("$compiler_dir/libraries/$library_name", $files["libs"][$library_name], $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories["main"], $format, true, $lib_object_naming_params); + + $log_content = (($compiler_config['logging'] === true) ? @file_get_contents($compiler_config['logFileName']) : ""); + if ($compiler_config['logging'] === true) + { + if ($log_content !== false) + { + $ret["log"] = $log_content; + file_put_contents($compiler_config["compiler_dir"]."/log", $log_content); + } + else + $ret["log"] = "Failed to access logfile."; + } + + if ($ARCHIVE_OPTION === true) + { + $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); + if ($arch_ret["success"] === false) + $ret["archive"] = $arch_ret["message"]; + else + $ret["archive"] = $ARCHIVE_PATH; + } + + if (!$ret["success"]) + return $ret; + + $objects_to_link = array_merge($objects_to_link, $files["libs"][$library_name]["o"]); + } + + // Step 7: Link all object files and create executable. + $object_files = ""; + foreach ($objects_to_link as $object) + $object_files .= " ".escapeshellarg("$object.o"); + + //Link core.a and every other object file to a .elf binary file + exec("$LD $LDFLAGS $target_arch $object_files $core_library -o $compiler_dir/files/$OUTPUT.elf $LDFLAGS_TAIL 2>&1", $output, $ret_link); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$LD $LDFLAGS $target_arch $object_files $core_library -o $compiler_dir/files/$OUTPUT.elf $LDFLAGS_TAIL\n", FILE_APPEND); + } + + if ($ret_link) + { + $originalLinkerOutput = implode("\n", $output); + // Log the fact that an error occurred during linking + $this->compiler_logger->addInfo($this->logger_id." - An error occurred during linking: ".json_encode($originalLinkerOutput)); + + /* + * Removes our weird tmp directory paths from the linker error output + */ + // Prebuilt arduino core library files (.a files) are cached and stored in '/tmp/objectFilesDirectory' + $linkerOutput = str_replace($this->object_directory .'/', '', $originalLinkerOutput); + // Object files produced from sketch compilation are stored in the same folder with the project code (/tmp/compiler.RANDOM/files) + $linkerOutput = str_replace("$compiler_dir/files/", '(file in sketch) ', $linkerOutput); + /* + * Of all the sub-directories of a library, only `utility` folder is currently taken under consideration, + * so it's removed manually. + * TODO: Find a unique way to mark library sub-folders in cached objects filenames + */ + $linkerOutput = str_replace('utility_______', 'utility/', $linkerOutput); + + // Remove the cached object path from the core library, if it exists in the error output + $boardConfig = "${mcu}_${f_cpu}_${core}_${variant}_${vid}_${pid}"; + $pathinfoResult = pathinfo(str_replace("/", "__", $CORE_DIR . "_"), PATHINFO_FILENAME); + $linkerOutput = str_replace($pathinfoResult . "_______" . $boardConfig . "_______", '', $linkerOutput); + + // Do the same for libraries' cached object files + $linkerOutput = str_replace($boardConfig, '', $linkerOutput); + // Handle both system and personal libraries and add a comment in order to make it clear where the file belongs + $linkerOutput = preg_replace('/(______)(.*)(\d*_cb_personal_lib_)(.*)(_______)/', "(personal library file) $4/", $linkerOutput); + $linkerOutput = preg_replace('/(______)(.*)(_______)/', '(library file) $2/', $linkerOutput); + // Add a new line which makes the output look better + $linkerOutput = str_replace('first defined here', "first defined here\n", $linkerOutput); + + // Log linker reformatted output + $this->compiler_logger->addInfo($this->logger_id." - Linker reformatted output: ".json_encode($linkerOutput)); + + $returner = array( + "success" => false, + "step" => 7, + "message" => $linkerOutput); + + if ($compiler_config['logging'] === true) + { + $log_content = @file_get_contents($compiler_config['logFileName']); + if (!$log_content) + $returner["log"] = "Failed to access logfile."; + else + { + file_put_contents($compiler_config["compiler_dir"]."/log", $log_content); + $returner["log"] = $log_content; + } + } + + if ($ARCHIVE_OPTION === true) + { + $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); + if ($arch_ret["success"] === false) + $returner["archive"] = $arch_ret["message"]; + else + $returner["archive"] = $ARCHIVE_PATH; + } + return $returner; + } + + // Step 8: Convert the output to the requested format and measure its + // size. + $tmpVar = $this->convertOutput("$compiler_dir/files", $format, $SIZE, $SIZE_FLAGS, $OBJCOPY, $OBJCOPY_FLAGS, $OUTPUT, $start_time, $compiler_config); + + if ($compiler_config['logging'] === true) + { + $log_content = @file_get_contents($compiler_config['logFileName']); + if (!$log_content) + $tmpVar["log"] = "Failed to access logfile."; + else + { + file_put_contents($compiler_config["compiler_dir"]."/log", $log_content); + $tmpVar["log"] = $log_content; + } + } + + if ($ARCHIVE_OPTION === true) + { + $arch_ret = $this->createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, $ARCHIVE_PATH); + if ($arch_ret["success"] === false) + $tmpVar["archive"] = $arch_ret["message"]; + else + $tmpVar["archive"] = $ARCHIVE_PATH; + } + return $tmpVar; + } + + private function requestValid(&$request) + { + $request = $this->preproc->validateInput($request); + if (!$request) + return array( + "success" => false, + "step" => 0, + "message" => "Invalid input."); + else return array("success" => true); + } + + private function createArchive($compiler_dir, $TEMP_DIR, $ARCHIVE_DIR, &$ARCHIVE_PATH) + { + if (!file_exists($ARCHIVE_PATH)) + { + // Create a directory in tmp folder and store archive files there + if (!file_exists("$TEMP_DIR/$ARCHIVE_DIR")) + { + //The code below was added to ensure that no error will be returned because of multithreaded execution. + $make_dir_success = @mkdir("$TEMP_DIR/$ARCHIVE_DIR", 0777, true); + if (!$make_dir_success && !is_dir("$TEMP_DIR/$ARCHIVE_DIR")) + { + usleep(rand(5000, 10000)); + $make_dir_success = @mkdir("$TEMP_DIR/$ARCHIVE_DIR", 0777, true); + } + if (!$make_dir_success) + return array("success" => false, "message" => "Failed to create archive directory."); + } + + do + { + $tar_random_name = uniqid(rand(), true).'.tar.gz'; + } while (file_exists("$TEMP_DIR/$ARCHIVE_DIR/$tar_random_name")); + $ARCHIVE_PATH = "$TEMP_DIR/$ARCHIVE_DIR/$tar_random_name"; + } + + // The archive files include all the files of the project and the libraries needed to compile it + exec("tar -zcf $ARCHIVE_PATH -C $TEMP_DIR/ ".pathinfo($compiler_dir, PATHINFO_BASENAME), $output, $ret_var); + + if ($ret_var != 0) + return array("success" => false, "message" => "Failed to archive project files."); + return array("success" => true); + } + + private function extractFiles($request, $temp_dir, &$dir, &$files, $suffix, $lib_extraction = false) + { + // Create a temporary directory to place all the files needed to process + // the compile request. This directory is created in $TMPDIR or /tmp by + // default and is automatically removed upon execution completion. + $cnt = 0; + if (!$dir) + do + { + $dir = @System::mktemp("-t $temp_dir/ -d compiler."); + $cnt++; + } while (!$dir && $cnt <= 2); + + if (!$dir) + return array( + "success" => false, + "step" => 1, + "message" => "Failed to create temporary directory."); + + $response = $this->utility->extractFiles("$dir/$suffix", $request, $lib_extraction); + + if ($response["success"] === false) + return $response; + $files = $response["files"]; + + return array("success" => true); + } + + private function preprocessIno(&$files) + { + foreach ($files["ino"] as $file) + { + $code = file_get_contents("$file.ino"); + $new_code = $this->preproc->convertInoToCpp($code, "$file.ino"); + $ret = file_put_contents("$file.cpp", $new_code); + + if ($code === false || !$new_code || !$ret) + return array( + "success" => false, + "step" => 2, + "message" => "Failed to preprocess file '$file.ino'."); + + $files["cpp"][] = array_shift($files["ino"]); + } + + return array("success" => true); + } + + public function preprocessHeaders($libraries, &$include_directories, $dir, $ARDUINO_CORES_DIR, $EXTERNAL_CORES_DIR, &$CORE_DIR, &$CORE_OVERRIDE_DIR, $version, &$core, &$variant) + { + try + { + // Create command-line arguments for header search paths. Note that the + // current directory is added to eliminate the difference between <> + // and "" in include preprocessor directives. + + // Check if the core or variant contains a semicolon. + // When a semicolon exists both the core folder and the core itself are specified. + // The same applies to the variant specification. + + $core_specs = array('folder' => "arduino", 'name' => $core, 'modified' => false); + $variant_specs = array('folder' => "arduino", 'name' => $variant, 'modified' => false); + + $tmp = explode(":", $core); + if (count($tmp) == 2) + { + $core_specs = array('folder' => $tmp[0], 'name' => $tmp[1], 'modified' => true); + $core = str_replace(":", "_", $core); //core name is used for object file naming, so it shouldn't contain any semicolons + } + elseif (count($tmp) != 1) + return array("success" => false, "step" => 3, "message" => "Invalid core specifier."); + + $tmp = explode(":", $variant); + if (count($tmp) == 2) + { + $variant_specs = array('folder' => $tmp[0], 'name' => $tmp[1], 'modified' => true); + $variant = str_replace(":", "_", $variant); //variant name is used for object file naming, so it shouldn't contain any semicolons + } + elseif (count($tmp) != 1) + return array("success" => false, "step" => 3, "message" => "Invalid variant specifier."); + + + $include_directories = array(); + + // Try to locate the core files + if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/".$core_specs['folder']."/cores/".$core_specs['name'])) + { + $CORE_DIR = "$ARDUINO_CORES_DIR/v$version/hardware/".$core_specs['folder']."/cores/".$core_specs['name']; + } + elseif (is_dir($EXTERNAL_CORES_DIR)) + { + if ($core_specs['modified'] === true) + { + if (file_exists("$EXTERNAL_CORES_DIR/".$core_specs['folder']."/cores/".$core_specs['name'])) + $CORE_DIR = "$EXTERNAL_CORES_DIR/".$core_specs['folder']."/cores/".$core_specs['name']; + } + elseif (false !== ($externals = @scandir($EXTERNAL_CORES_DIR))) + { + foreach ($externals as $dirname) + if (is_dir("$EXTERNAL_CORES_DIR/$dirname/") && $dirname != "." && $dirname != ".." && file_exists("$EXTERNAL_CORES_DIR/$dirname/cores/".$core_specs['name'])) + { + $CORE_DIR = "$EXTERNAL_CORES_DIR/$dirname/cores/".$core_specs['name']; + break; + } + } + } + + if (empty($CORE_DIR)) + return array("success" => false, "step" => 3, "message" => "Failed to detect core files."); + + // Try to locate the variant + if ($variant != "") + { + if (file_exists("$ARDUINO_CORES_DIR/v$version/hardware/".$variant_specs['folder']."/variants/".$variant_specs['name'])) + $variant_dir = "$ARDUINO_CORES_DIR/v$version/hardware/".$variant_specs['folder']."/variants/".$variant_specs['name']; + else + { + if (is_dir($EXTERNAL_CORES_DIR)) + { + if ($variant_specs['modified'] === true) + { + if (file_exists("$EXTERNAL_CORES_DIR/".$variant_specs['folder']."/variants/".$variant_specs['name'])) + $variant_dir = "$EXTERNAL_CORES_DIR/".$variant_specs['folder']."/variants/".$variant_specs['name']; + } + elseif (false !== ($externals = @scandir($EXTERNAL_CORES_DIR))) + { + foreach ($externals as $dirname) + if (is_dir("$EXTERNAL_CORES_DIR/$dirname") && $dirname != "." && $dirname != "..") + if ($variant != "" && file_exists("$EXTERNAL_CORES_DIR/$dirname/variants/".$variant_specs['name'])) + { + $variant_dir = "$EXTERNAL_CORES_DIR/$dirname/variants/".$variant_specs['name']; + break; + } + } + } + } + } + + if (!empty($variant) && empty($variant_dir)) + return array("success" => false, "step" => 3, "message" => "Failed to detect variant."); // Check the override file directories for files that override the requested cores - if (is_dir("$EXTERNAL_CORES_DIR/override_cores/".$core_specs['name']."/") ) + if (is_dir("$EXTERNAL_CORES_DIR/override_cores/".$core_specs['name']."/")) $CORE_OVERRIDE_DIR = "$EXTERNAL_CORES_DIR/override_cores/".$core_specs['name']."/"; else $CORE_OVERRIDE_DIR = ""; $include_directories["core"] = ((!empty($CORE_OVERRIDE_DIR)) && ($CORE_OVERRIDE_DIR != "")) ? " -I$CORE_OVERRIDE_DIR" : ""; - $include_directories["core"] .= " -I$CORE_DIR"; + $include_directories["core"] .= " -I$CORE_DIR"; $include_directories["core"] .= (!empty($variant_dir)) ? " -I$variant_dir" : ""; - $include_directories["main"] = $include_directories["core"]; - foreach ($libraries as $library_name => $library_files) - $include_directories["main"] .= " -I$dir/libraries/$library_name"; - } - catch(\Exception $e) - { - return array("success" => false, "step" => 3, "message" => "Unknown Error:\n".$e->getMessage()); - } - - return array("success" => true); - } - - private function doCompile($compiler_config, &$files, $dir, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories, $format, $caching = false, $name_params = null) - { - if ($format == "syntax") - { - $CFLAGS .= " -fsyntax-only"; - $CPPFLAGS .= " -fsyntax-only"; - } - - foreach (array("c", "cpp", "S") as $ext) - { - foreach ($files[$ext] as $file) - { - if($caching){ - $name_params['core'] = str_replace(":", "_", $name_params['core']); - $name_params['variant'] = str_replace(":", "_", $name_params['variant']); - $object_filename = "$this->object_directory/${name_params['mcu']}_${name_params['f_cpu']}_${name_params['core']}_${name_params['variant']}_${name_params['vid']}_${name_params['pid']}______${name_params['library']}_______".((pathinfo(pathinfo($file, PATHINFO_DIRNAME), PATHINFO_FILENAME) == "utility") ? "utility_______" : "") .pathinfo($file, PATHINFO_FILENAME); - $object_file = $object_filename; - //Lock the file so that only one compiler instance (thread) will compile every library object file - $lock = fopen("$object_file.o.LOCK", "w"); - $lock_check = flock($lock, LOCK_EX); - } - else - $object_file = $file; - - if(!file_exists("$object_file.o")){ - // From hereon, $file is shell escaped and thus should only be used in calls - // to exec(). - $file = escapeshellarg($file); - $object_file = escapeshellarg($object_file); - - //replace exec() calls with $this->utility->debug_exec() for debugging - if ($ext == "c") - { - exec("$CC $CFLAGS $core_includes $target_arch $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$CC $CFLAGS $core_includes $target_arch $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); - } - } - elseif ($ext == "cpp") - { - exec("$CPP $CPPFLAGS $core_includes $target_arch -MMD $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$CPP $CPPFLAGS $core_includes $target_arch -MMD $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); - } - } - elseif ($ext == "S") - { - exec("$AS $ASFLAGS $target_arch $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$AS $ASFLAGS $target_arch $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); - } - } - if (isset($ret_compile) && $ret_compile) - { - $avr_output = implode("\n", $output); - unset($output); - exec("$CLANG $CLANG_FLAGS $core_includes $clang_target_arch $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$CLANG $CLANG_FLAGS $core_includes $clang_target_arch $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); - } - - $output = $this->postproc->ansi_to_html(implode("\n", $output)); - - $resp = array( - "success" => false, - "step" => 4, - "debug" => $avr_output); - - /** - * When an error occurs, compare the output of both avr-gcc and clang - * and if significant differences are detected, return a modified version of the clang output. - */ - $clangElements = $this->getClangErrorFileList ($output); - $this->compiler_logger->addInfo($this->logger_id . " - Clang reported files: " . implode(" | ", array_keys($clangElements))); - $gccElements = $this->getGccErrorFileList ($avr_output); - $this->compiler_logger->addInfo($this->logger_id . " - Gcc reported files: " . implode(" | ", array_keys($gccElements))); - - if (array_diff(array_keys($clangElements), array_keys($gccElements))) { - - $resp["old_message"] = $output; - $this->compiler_logger->addInfo($this->logger_id . " - Mismatch between clang and gcc output found."); - - $next_clang_output = $this->cleanUpClangOutput ($output, $compiler_config, "asm"); - - $clangElements = $this->getClangErrorFileList ($next_clang_output); - $this->compiler_logger->addInfo($this->logger_id . " - Clang reported files after removing asm: " . implode(" | ", array_keys($clangElements))); - - if (array_diff(array_keys($clangElements), array_keys($gccElements))) { - $this->compiler_logger->addInfo($this->logger_id . " - Mismatch between clang and gcc output found after removing assembly messages."); - $final_clang_output = $this->cleanUpClangOutput ($next_clang_output, $compiler_config, "non_asm"); - - $clangElements = $this->getClangErrorFileList ($final_clang_output); - if (array_diff(array_keys($clangElements), array_keys($gccElements))) { - $this->compiler_logger->addInfo($this->logger_id . " - Mismatch between clang and gcc output found after removing assembly/library/core messages."); - }else { - $this->compiler_logger->addInfo($this->logger_id . " - Clang and gcc issue solved. Both report same files with errors."); - } - $this->compiler_logger->addInfo($this->logger_id . " - Gcc output: " . json_encode($avr_output)); - $this->compiler_logger->addInfo($this->logger_id . " - Clang initial output: " . json_encode($output)); - $this->compiler_logger->addInfo($this->logger_id . " - Clang reformated output: " . json_encode($final_clang_output)); - $final_clang_output = $this->pathRemover ($final_clang_output, $compiler_config); - $resp["message"] = $final_clang_output; - if ($resp["message"] == "") - $resp["message"] = $this->pathRemover ($output, $compiler_config); - return $resp; - }else { - $this->compiler_logger->addInfo($this->logger_id . " - Gcc output: " . json_encode($avr_output)); - $this->compiler_logger->addInfo($this->logger_id . " - Clang initial output: " . json_encode($output)); - $this->compiler_logger->addInfo($this->logger_id . " - Clang reformated output: " . json_encode($next_clang_output)); - $next_clang_output = $this->pathRemover ($next_clang_output, $compiler_config); - $resp["message"] = $next_clang_output; - if ($resp["message"] == "") - $resp["message"] = $this->pathRemover ($output, $compiler_config); - return $resp; - } - } - - $resp["message"] = $this->pathRemover ($output, $compiler_config); - if ($resp["message"] == "") - $resp["message"] = $this->pathRemover($avr_output, $compiler_config); - return $resp; - } - unset($output); - if ($caching && $lock_check){ - flock($lock, LOCK_UN); - fclose($lock); - } - } - elseif ($caching && $lock_check){ - if($compiler_config['logging']) - file_put_contents($compiler_config['logFileName'],"Using previously compiled version of $object_file.o\n", FILE_APPEND); - flock($lock, LOCK_UN); - fclose($lock); - } - - if(!$caching){ - $files["o"][] = array_shift($files[$ext]); - } - else{ - $files["o"][] = $object_filename; - array_shift($files[$ext]); - } - } - } - - return array("success" => true); - } - - private function convertOutput($dir, $format, $SIZE, $SIZE_FLAGS, $OBJCOPY, $OBJCOPY_FLAGS, $OUTPUT, $start_time, $compiler_config) - { - if ($format == "elf") - { - $ret_objcopy = false; - exec("$SIZE $SIZE_FLAGS --target=elf32-avr $dir/$OUTPUT.elf | awk 'FNR == 2 {print $1+$2}'", $size, $ret_size); // FIXME - - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$SIZE $SIZE_FLAGS --target=elf32-avr $dir/$OUTPUT.elf | awk 'FNR == 2 {print $1+$2}'\n", FILE_APPEND); - } - $content = base64_encode(file_get_contents("$dir/$OUTPUT.elf")); - } - elseif ($format == "binary") - { - exec("$OBJCOPY $OBJCOPY_FLAGS -O binary $dir/$OUTPUT.elf $dir/$OUTPUT.bin", $dummy, $ret_objcopy); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$OBJCOPY $OBJCOPY_FLAGS -O binary $dir/$OUTPUT.elf $dir/$OUTPUT.bin\n", FILE_APPEND); - } - - exec("$SIZE $SIZE_FLAGS --target=binary $dir/$OUTPUT.bin | awk 'FNR == 2 {print $1+$2}'", $size, $ret_size); // FIXME - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$SIZE $SIZE_FLAGS --target=binary $dir/$OUTPUT.bin | awk 'FNR == 2 {print $1+$2}'\n", FILE_APPEND); - } - $content = base64_encode(file_get_contents("$dir/$OUTPUT.bin")); - } - elseif ($format == "hex") - { - exec("$OBJCOPY $OBJCOPY_FLAGS -O ihex $dir/$OUTPUT.elf $dir/$OUTPUT.hex", $dummy, $ret_objcopy); - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$OBJCOPY $OBJCOPY_FLAGS -O ihex $dir/$OUTPUT.elf $dir/$OUTPUT.hex\n", FILE_APPEND); - } - - exec("$SIZE $SIZE_FLAGS --target=ihex $dir/$OUTPUT.hex | awk 'FNR == 2 {print $1+$2}'", $size, $ret_size); // FIXME - if($compiler_config['logging']){ - file_put_contents($compiler_config['logFileName'],"$SIZE $SIZE_FLAGS --target=ihex $dir/$OUTPUT.hex | awk 'FNR == 2 {print $1+$2}'\n", FILE_APPEND); - } - - $content = file_get_contents("$dir/$OUTPUT.hex"); - } - - // If everything went well, return the reply to the caller. - if ($ret_objcopy || $ret_size || $content === false) - return array( - "success" => false, - "step" => 8, - "message" => "There was a problem while generating the your binary file"); - else - return array( - "success" => true, - "time" => microtime(true) - $start_time, - "size" => $size[0], - "output" => $content); - - } - - private function set_avr($version, $ARDUINO_CORES_DIR, $BINUTILS, &$CC, &$CPP, &$AS, &$AR, &$LD, &$OBJCOPY, &$SIZE) - { - // External binaries. - $binaries = array("cc" => "-gcc", "cpp" => "-g++", "as" => "-gcc", "ar" => "-ar", "ld" => "-gcc", "objcopy" => "-objcopy", "size" => "-size"); - - $binpaths = array(); - foreach ($binaries as $key => $value){ - if (!file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/bin/avr$value")) - $binpaths[$key] = "$BINUTILS/avr$value"; - else - $binpaths[$key] = "$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/bin/avr$value"; - } - - $CC = $binpaths["cc"]; - $CPP = $binpaths["cpp"]; - $AS = $binpaths["as"]; - $AR = $binpaths["ar"]; - $LD = $binpaths["ld"]; - $OBJCOPY = $binpaths["objcopy"]; - $SIZE = $binpaths["size"]; - - } - private function set_values($compiler_config, - &$BINUTILS, &$CLANG, &$CFLAGS, &$CPPFLAGS, - &$ASFLAGS, &$ARFLAGS, &$LDFLAGS, &$LDFLAGS_TAIL, &$CLANG_FLAGS, &$OBJCOPY_FLAGS, &$SIZE_FLAGS, - &$OUTPUT, &$ARDUINO_CORES_DIR, &$EXTERNAL_CORES_DIR, &$TEMP_DIR, &$ARCHIVE_DIR, &$AUTOCC_DIR, &$PYTHON, &$AUTOCOMPLETER) - { - // External binaries. - //If the current version of the core files does not include its own binaries, then use the default - //ones included in the binutils parameter - $BINUTILS = $compiler_config["binutils"]; - //Clang is used to return the output in case of an error, it's version independent, so its - //value is set by set_values function. - - $LDLIBRARYPATH="LD_LIBRARY_PATH=" . $compiler_config["arduino_cores_dir"] . "/clang/v3_5/lib:\$LD_LIBRARY_PATH"; - $CLANG = $LDLIBRARYPATH . " " . $compiler_config["clang"]; + $include_directories["main"] = $include_directories["core"]; + foreach ($libraries as $library_name => $library_files) + $include_directories["main"] .= " -I$dir/libraries/$library_name"; + } catch (\Exception $e) + { + return array("success" => false, "step" => 3, "message" => "Unknown Error:\n".$e->getMessage()); + } + + return array("success" => true); + } + + private function doCompile($compiler_config, &$files, $dir, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories, $format, $caching = false, $name_params = null) + { + if ($format == "syntax") + { + $CFLAGS .= " -fsyntax-only"; + $CPPFLAGS .= " -fsyntax-only"; + } + + foreach (array("c", "cpp", "S") as $ext) + { + foreach ($files[$ext] as $file) + { + if ($caching) + { + $name_params['core'] = str_replace(":", "_", $name_params['core']); + $name_params['variant'] = str_replace(":", "_", $name_params['variant']); + $object_filename = "$this->object_directory/${name_params['mcu']}_${name_params['f_cpu']}_${name_params['core']}_${name_params['variant']}_${name_params['vid']}_${name_params['pid']}______${name_params['library']}_______".((pathinfo(pathinfo($file, PATHINFO_DIRNAME), PATHINFO_FILENAME) == "utility") ? "utility_______" : "").pathinfo($file, PATHINFO_FILENAME); + $object_file = $object_filename; + //Lock the file so that only one compiler instance (thread) will compile every library object file + $lock = fopen("$object_file.o.LOCK", "w"); + $lock_check = flock($lock, LOCK_EX); + } + else + $object_file = $file; + + if (!file_exists("$object_file.o")) + { + // From hereon, $file is shell escaped and thus should only be used in calls + // to exec(). + $file = escapeshellarg($file); + $object_file = escapeshellarg($object_file); + + //replace exec() calls with $this->utility->execWithDebugging() for debugging + if ($ext == "c") + { + exec("$CC $CFLAGS $core_includes $target_arch $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$CC $CFLAGS $core_includes $target_arch $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); + } + } + elseif ($ext == "cpp") + { + exec("$CPP $CPPFLAGS $core_includes $target_arch -MMD $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$CPP $CPPFLAGS $core_includes $target_arch -MMD $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); + } + } + elseif ($ext == "S") + { + exec("$AS $ASFLAGS $target_arch $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$AS $ASFLAGS $target_arch $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); + } + } + if (isset($ret_compile) && $ret_compile) + { + $avr_output = implode("\n", $output); + unset($output); + exec("$CLANG $CLANG_FLAGS $core_includes $clang_target_arch $include_directories -c -o $object_file.o $file.$ext 2>&1", $output, $ret_compile); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$CLANG $CLANG_FLAGS $core_includes $clang_target_arch $include_directories -c -o $object_file.o $file.$ext\n", FILE_APPEND); + } + + $output = $this->postproc->convertANSItoHTML(implode("\n", $output)); + + $resp = array( + "success" => false, + "step" => 4, + "debug" => $avr_output); + + /** + * When an error occurs, compare the output of both avr-gcc and clang + * and if significant differences are detected, return a modified version of the clang output. + */ + $clangElements = $this->getClangErrorFileList($output); + $this->compiler_logger->addInfo($this->logger_id." - Clang reported files: ".implode(" | ", array_keys($clangElements))); + $gccElements = $this->getGccErrorFileList($avr_output); + $this->compiler_logger->addInfo($this->logger_id." - Gcc reported files: ".implode(" | ", array_keys($gccElements))); + + if (array_diff(array_keys($clangElements), array_keys($gccElements))) + { + + $resp["old_message"] = $output; + $this->compiler_logger->addInfo($this->logger_id." - Mismatch between clang and gcc output found."); + + $next_clang_output = $this->cleanUpClangOutput($output, $compiler_config, "asm"); + + $clangElements = $this->getClangErrorFileList($next_clang_output); + $this->compiler_logger->addInfo($this->logger_id." - Clang reported files after removing asm: ".implode(" | ", array_keys($clangElements))); + + if (array_diff(array_keys($clangElements), array_keys($gccElements))) + { + $this->compiler_logger->addInfo($this->logger_id." - Mismatch between clang and gcc output found after removing assembly messages."); + $final_clang_output = $this->cleanUpClangOutput($next_clang_output, $compiler_config, "non_asm"); + + $clangElements = $this->getClangErrorFileList($final_clang_output); + if (array_diff(array_keys($clangElements), array_keys($gccElements))) + { + $this->compiler_logger->addInfo($this->logger_id." - Mismatch between clang and gcc output found after removing assembly/library/core messages."); + } + else + { + $this->compiler_logger->addInfo($this->logger_id." - Clang and gcc issue solved. Both report same files with errors."); + } + $this->compiler_logger->addInfo($this->logger_id." - Gcc output: ".json_encode($avr_output)); + $this->compiler_logger->addInfo($this->logger_id." - Clang initial output: ".json_encode($output)); + $this->compiler_logger->addInfo($this->logger_id." - Clang reformated output: ".json_encode($final_clang_output)); + $final_clang_output = $this->pathRemover($final_clang_output, $compiler_config); + $resp["message"] = $final_clang_output; + if ($resp["message"] == "") + $resp["message"] = $this->pathRemover($output, $compiler_config); + return $resp; + } + else + { + $this->compiler_logger->addInfo($this->logger_id." - Gcc output: ".json_encode($avr_output)); + $this->compiler_logger->addInfo($this->logger_id." - Clang initial output: ".json_encode($output)); + $this->compiler_logger->addInfo($this->logger_id." - Clang reformated output: ".json_encode($next_clang_output)); + $next_clang_output = $this->pathRemover($next_clang_output, $compiler_config); + $resp["message"] = $next_clang_output; + if ($resp["message"] == "") + $resp["message"] = $this->pathRemover($output, $compiler_config); + return $resp; + } + } + + $resp["message"] = $this->pathRemover($output, $compiler_config); + if ($resp["message"] == "") + $resp["message"] = $this->pathRemover($avr_output, $compiler_config); + return $resp; + } + unset($output); + if ($caching && $lock_check) + { + flock($lock, LOCK_UN); + fclose($lock); + } + } + elseif ($caching && $lock_check) + { + if ($compiler_config['logging']) + file_put_contents($compiler_config['logFileName'], "Using previously compiled version of $object_file.o\n", FILE_APPEND); + flock($lock, LOCK_UN); + fclose($lock); + } + + if (!$caching) + { + $files["o"][] = array_shift($files[$ext]); + } + else + { + $files["o"][] = $object_filename; + array_shift($files[$ext]); + } + } + } + + return array("success" => true); + } + + private function convertOutput($dir, $format, $SIZE, $SIZE_FLAGS, $OBJCOPY, $OBJCOPY_FLAGS, $OUTPUT, $start_time, $compiler_config) + { + if ($format == "elf") + { + $ret_objcopy = false; + exec("$SIZE $SIZE_FLAGS --target=elf32-avr $dir/$OUTPUT.elf | awk 'FNR == 2 {print $1+$2}'", $size, $ret_size); // FIXME + + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$SIZE $SIZE_FLAGS --target=elf32-avr $dir/$OUTPUT.elf | awk 'FNR == 2 {print $1+$2}'\n", FILE_APPEND); + } + $content = base64_encode(file_get_contents("$dir/$OUTPUT.elf")); + } + elseif ($format == "binary") + { + exec("$OBJCOPY $OBJCOPY_FLAGS -O binary $dir/$OUTPUT.elf $dir/$OUTPUT.bin", $dummy, $ret_objcopy); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$OBJCOPY $OBJCOPY_FLAGS -O binary $dir/$OUTPUT.elf $dir/$OUTPUT.bin\n", FILE_APPEND); + } + + exec("$SIZE $SIZE_FLAGS --target=binary $dir/$OUTPUT.bin | awk 'FNR == 2 {print $1+$2}'", $size, $ret_size); // FIXME + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$SIZE $SIZE_FLAGS --target=binary $dir/$OUTPUT.bin | awk 'FNR == 2 {print $1+$2}'\n", FILE_APPEND); + } + $content = base64_encode(file_get_contents("$dir/$OUTPUT.bin")); + } + elseif ($format == "hex") + { + exec("$OBJCOPY $OBJCOPY_FLAGS -O ihex $dir/$OUTPUT.elf $dir/$OUTPUT.hex", $dummy, $ret_objcopy); + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$OBJCOPY $OBJCOPY_FLAGS -O ihex $dir/$OUTPUT.elf $dir/$OUTPUT.hex\n", FILE_APPEND); + } + + exec("$SIZE $SIZE_FLAGS --target=ihex $dir/$OUTPUT.hex | awk 'FNR == 2 {print $1+$2}'", $size, $ret_size); // FIXME + if ($compiler_config['logging']) + { + file_put_contents($compiler_config['logFileName'], "$SIZE $SIZE_FLAGS --target=ihex $dir/$OUTPUT.hex | awk 'FNR == 2 {print $1+$2}'\n", FILE_APPEND); + } + + $content = file_get_contents("$dir/$OUTPUT.hex"); + } + + // If everything went well, return the reply to the caller. + if ($ret_objcopy || $ret_size || $content === false) + return array( + "success" => false, + "step" => 8, + "message" => "There was a problem while generating the your binary file"); + else + return array( + "success" => true, + "time" => microtime(true) - $start_time, + "size" => $size[0], + "output" => $content); + + } + + private function setAVR($version, $ARDUINO_CORES_DIR, $BINUTILS, &$CC, &$CPP, &$AS, &$AR, &$LD, &$OBJCOPY, &$SIZE) + { + // External binaries. + $binaries = array("cc" => "-gcc", "cpp" => "-g++", "as" => "-gcc", "ar" => "-ar", "ld" => "-gcc", "objcopy" => "-objcopy", "size" => "-size"); + + $binpaths = array(); + foreach ($binaries as $key => $value) + { + if (!file_exists("$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/bin/avr$value")) + $binpaths[$key] = "$BINUTILS/avr$value"; + else + $binpaths[$key] = "$ARDUINO_CORES_DIR/v$version/hardware/tools/avr/bin/avr$value"; + } + + $CC = $binpaths["cc"]; + $CPP = $binpaths["cpp"]; + $AS = $binpaths["as"]; + $AR = $binpaths["ar"]; + $LD = $binpaths["ld"]; + $OBJCOPY = $binpaths["objcopy"]; + $SIZE = $binpaths["size"]; + + } + + private function setValues($compiler_config, + &$BINUTILS, &$CLANG, &$CFLAGS, &$CPPFLAGS, + &$ASFLAGS, &$ARFLAGS, &$LDFLAGS, &$LDFLAGS_TAIL, &$CLANG_FLAGS, &$OBJCOPY_FLAGS, &$SIZE_FLAGS, + &$OUTPUT, &$ARDUINO_CORES_DIR, &$EXTERNAL_CORES_DIR, &$TEMP_DIR, &$ARCHIVE_DIR, &$AUTOCC_DIR, &$PYTHON, &$AUTOCOMPLETER) + { + // External binaries. + //If the current version of the core files does not include its own binaries, then use the default + //ones included in the binutils parameter + $BINUTILS = $compiler_config["binutils"]; + //Clang is used to return the output in case of an error, it's version independent, so its + //value is set by setValues function. + + $LDLIBRARYPATH = "LD_LIBRARY_PATH=".$compiler_config["arduino_cores_dir"]."/clang/v3_5/lib:\$LD_LIBRARY_PATH"; + $CLANG = $LDLIBRARYPATH." ".$compiler_config["clang"]; //Path to Python binaries, needed for the execution of the autocompletion script. - $PYTHONPATH="PYTHONPATH=" . $compiler_config["arduino_cores_dir"] . "/clang/v3_5/bindings/python:\$PYTHONPATH"; - $PYTHON = $LDLIBRARYPATH . " " . $PYTHONPATH . " " . $compiler_config["python"]; - - // Standard command-line arguments used by the binaries. - $CFLAGS = $compiler_config["cflags"]; - $CPPFLAGS = $compiler_config["cppflags"]; - $ASFLAGS = $compiler_config["asflags"]; - $ARFLAGS = $compiler_config["arflags"]; - $LDFLAGS = $compiler_config["ldflags"]; - $LDFLAGS_TAIL = $compiler_config["ldflags_tail"]; - $CLANG_FLAGS = $compiler_config["clang_flags"]; - $OBJCOPY_FLAGS = $compiler_config["objcopy_flags"]; - $SIZE_FLAGS = $compiler_config["size_flags"]; - // The default name of the output file. - $OUTPUT = $compiler_config["output"]; - // The tmp folder where logfiles and object files are placed - $TEMP_DIR = $compiler_config["temp_dir"]; - // The directory name where archive files are stored in $TEMP_DIR - $ARCHIVE_DIR = $compiler_config["archive_dir"]; + $PYTHONPATH = "PYTHONPATH=".$compiler_config["arduino_cores_dir"]."/clang/v3_5/bindings/python:\$PYTHONPATH"; + $PYTHON = $LDLIBRARYPATH." ".$PYTHONPATH." ".$compiler_config["python"]; + + // Standard command-line arguments used by the binaries. + $CFLAGS = $compiler_config["cflags"]; + $CPPFLAGS = $compiler_config["cppflags"]; + $ASFLAGS = $compiler_config["asflags"]; + $ARFLAGS = $compiler_config["arflags"]; + $LDFLAGS = $compiler_config["ldflags"]; + $LDFLAGS_TAIL = $compiler_config["ldflags_tail"]; + $CLANG_FLAGS = $compiler_config["clang_flags"]; + $OBJCOPY_FLAGS = $compiler_config["objcopy_flags"]; + $SIZE_FLAGS = $compiler_config["size_flags"]; + // The default name of the output file. + $OUTPUT = $compiler_config["output"]; + // The tmp folder where logfiles and object files are placed + $TEMP_DIR = $compiler_config["temp_dir"]; + // The directory name where archive files are stored in $TEMP_DIR + $ARCHIVE_DIR = $compiler_config["archive_dir"]; // The directory where autocompletion files are stored. $AUTOCC_DIR = $compiler_config["autocompletion_dir"]; // The name of the python script that will be executed for autocompletion. $AUTOCOMPLETER = $compiler_config["autocompleter"]; - // Path to arduino-core-files repository. - $ARDUINO_CORES_DIR = $compiler_config["arduino_cores_dir"]; - // Path to external core files (for example arduino ATtiny) - $EXTERNAL_CORES_DIR = $compiler_config["external_core_files"]; - } - - private function set_variables($request, &$format, &$libraries, &$version, &$mcu, &$f_cpu, &$core, &$variant, &$vid, &$pid, &$compiler_config) - { - // Extract the request options for easier access. - $format = $request["format"]; - $libraries = $request["libraries"]; - $version = $request["version"]; - $mcu = $request["build"]["mcu"]; - $f_cpu = $request["build"]["f_cpu"]; - $core = $request["build"]["core"]; - // Some cores do not specify any variants. In this case, set variant to be an empty string - if (!array_key_exists("variant", $request["build"])) - $variant = ""; - else - $variant = $request["build"]["variant"]; - - if ($format == "autocomplete") { + // Path to arduino-core-files repository. + $ARDUINO_CORES_DIR = $compiler_config["arduino_cores_dir"]; + // Path to external core files (for example arduino ATtiny) + $EXTERNAL_CORES_DIR = $compiler_config["external_core_files"]; + } + + private function setVariables($request, &$format, &$libraries, &$version, &$mcu, &$f_cpu, &$core, &$variant, &$vid, &$pid, &$compiler_config) + { + // Extract the request options for easier access. + $format = $request["format"]; + $libraries = $request["libraries"]; + $version = $request["version"]; + $mcu = $request["build"]["mcu"]; + $f_cpu = $request["build"]["f_cpu"]; + $core = $request["build"]["core"]; + // Some cores do not specify any variants. In this case, set variant to be an empty string + if (!array_key_exists("variant", $request["build"])) + $variant = ""; + else + $variant = $request["build"]["variant"]; + + if ($format == "autocomplete") + { $compiler_config["autocmpfile"] = $request["position"]["file"]; $compiler_config["autocmprow"] = $request["position"]["row"]; $compiler_config["autocmpcol"] = $request["position"]["column"]; - $compiler_config["autocmpmaxresults"] = $request["maxresults"]; + $compiler_config["autocmpmaxresults"] = 500; $compiler_config["autocmpprefix"] = $request["prefix"]; } - // Set the appropriate variables for vid and pid (Leonardo). + // Set the appropriate variables for vid and pid (Leonardo). - $vid = (isset($request["build"]["vid"])) ? $request["build"]["vid"] : "null"; - $pid = (isset($request["build"]["pid"])) ? $request["build"]["pid"] : "null"; - } + $vid = (isset($request["build"]["vid"])) ? $request["build"]["vid"] : "null"; + $pid = (isset($request["build"]["pid"])) ? $request["build"]["pid"] : "null"; + } - private function setLoggingParams($request, &$compiler_config, $temp_dir, $compiler_dir) - { - //Check if $request['logging'] exists and is true, then make the logfile, otherwise set - //$compiler_config['logdir'] to false and return to caller - if(array_key_exists('logging', $request) && $request['logging']) - { - /* - Generate a random part for the log name based on current date and time, - in order to avoid naming different Blink projects for which we need logfiles - */ - $randPart = date('YmdHis'); - /* - Then find the name of the arduino file which usually is the project name itself - and mix them all together - */ - - foreach($request['files'] as $file){ - if(strcmp(pathinfo($file['filename'], PATHINFO_EXTENSION), "ino") == 0){$basename = pathinfo($file['filename'], PATHINFO_FILENAME);} - } - if(!isset($basename)){$basename="logfile";} - - $compiler_config['logging'] = true; - $directory = $temp_dir."/".$compiler_config['logdir']; - //The code below was added to ensure that no error will be returned because of multithreaded execution. - if(!file_exists($directory)){ - $make_dir_success = @mkdir($directory, 0777, true); - if (!$make_dir_success && !is_dir($directory)) { - usleep(rand( 5000 , 10000 )); - $make_dir_success = @mkdir($directory, 0777, true); - } - if(!$make_dir_success) - return array("success"=>false, "message"=>"Failed to create logfiles directory."); - } - - $compiler_part = str_replace(".", "_", substr($compiler_dir, strpos($compiler_dir, "compiler"))); - - $compiler_config['logFileName'] = $directory ."/". $basename ."_".$compiler_part."_". $randPart .".txt"; - - file_put_contents($compiler_config['logFileName'], ''); - } - elseif(!array_key_exists('logging', $request) or !$request['logging']) - $compiler_config['logging'] = false; - - return array("success"=>true); - } - - - /** - \brief Reads all core files from the respective directory and passes their contents to extractFiles function - which then writes them to the compiler temp directory - - \param string $core_files_directory The directory containing the core files. - \param string $tmp_compiler The tmp directory where the actual compilation process takes place. - \return array An array containing the function results. - */ - private function makeCoresTmp($core_files_directory, $core_overrd_directory, $temp_directory, $tmp_compiler, &$files){ - - $core = array(); - if(false === ($scanned_files = @scandir($core_files_directory))) - return array( "success"=>false, "step"=>5, "message"=>"Failed to read core files." ); - - // Get the contents of the core files - foreach ($scanned_files as $core_file) - if(!is_dir("$core_files_directory/$core_file")){ - if (!empty($core_overrd_directory) && $core_overrd_directory !="" && file_exists("$core_overrd_directory/$core_file")) + private function setLoggingParams($request, &$compiler_config, $temp_dir, $compiler_dir) + { + //Check if $request['logging'] exists and is true, then make the logfile, otherwise set + //$compiler_config['logdir'] to false and return to caller + if (array_key_exists('logging', $request) && $request['logging']) + { + /* + Generate a random part for the log name based on current date and time, + in order to avoid naming different Blink projects for which we need logfiles + */ + $randPart = date('YmdHis'); + /* + Then find the name of the arduino file which usually is the project name itself + and mix them all together + */ + + foreach ($request['files'] as $file) + { + if (strcmp(pathinfo($file['filename'], PATHINFO_EXTENSION), "ino") == 0) + { + $basename = pathinfo($file['filename'], PATHINFO_FILENAME); + } + } + if (!isset($basename)) + { + $basename = "logfile"; + } + + $compiler_config['logging'] = true; + $directory = $temp_dir."/".$compiler_config['logdir']; + //The code below was added to ensure that no error will be returned because of multithreaded execution. + if (!file_exists($directory)) + { + $make_dir_success = @mkdir($directory, 0777, true); + if (!$make_dir_success && !is_dir($directory)) + { + usleep(rand(5000, 10000)); + $make_dir_success = @mkdir($directory, 0777, true); + } + if (!$make_dir_success) + return array("success" => false, "message" => "Failed to create logfiles directory."); + } + + $compiler_part = str_replace(".", "_", substr($compiler_dir, strpos($compiler_dir, "compiler"))); + + $compiler_config['logFileName'] = $directory."/".$basename."_".$compiler_part."_".$randPart.".txt"; + + file_put_contents($compiler_config['logFileName'], ''); + } + elseif (!array_key_exists('logging', $request) || (!$request['logging'])) + $compiler_config['logging'] = false; + + return array("success" => true); + } + + + /** + * \brief Reads all core files from the respective directory and passes their contents to extractFiles function + * which then writes them to the compiler temp directory + * + * \param string $core_files_directory The directory containing the core files. + * \param string $tmp_compiler The tmp directory where the actual compilation process takes place. + * \return array An array containing the function results. + */ + private function makeCoresTmp($core_files_directory, $core_overrd_directory, $temp_directory, $tmp_compiler, &$files) + { + + $core = array(); + if (false === ($scanned_files = @scandir($core_files_directory))) + return array("success" => false, "step" => 5, "message" => "Failed to read core files."); + + // Get the contents of the core files + foreach ($scanned_files as $core_file) + if (!is_dir("$core_files_directory/$core_file")) + { + if (!empty($core_overrd_directory) && $core_overrd_directory != "" && file_exists("$core_overrd_directory/$core_file")) $core[] = array("filename" => $core_file, "content" => file_get_contents("$core_overrd_directory/$core_file"), "filepath" => "$core_overrd_directory/$core_file"); else $core[] = array("filename" => $core_file, "content" => file_get_contents("$core_files_directory/$core_file"), "filepath" => "$core_files_directory/$core_file"); } - // Check if the version of the core files includes an avr-libc directory and scan - if(file_exists("$core_files_directory/avr-libc")){ - if(false === ($scanned_avr_files = @scandir("$core_files_directory/avr-libc"))) - return array( "success"=>false, "step"=>5, "message"=>"Failed to read core files." ); - foreach($scanned_avr_files as $avr_file) - if(!is_dir("$core_files_directory/avr-libc/$avr_file")){ - if (!empty($core_overrd_directory) && $core_overrd_directory !="" && file_exists("$core_overrd_directory/avr-libc/$avr_file")) + // Check if the version of the core files includes an avr-libc directory and scan + if (file_exists("$core_files_directory/avr-libc")) + { + if (false === ($scanned_avr_files = @scandir("$core_files_directory/avr-libc"))) + return array("success" => false, "step" => 5, "message" => "Failed to read core files."); + foreach ($scanned_avr_files as $avr_file) + if (!is_dir("$core_files_directory/avr-libc/$avr_file")) + { + if (!empty($core_overrd_directory) && $core_overrd_directory != "" && file_exists("$core_overrd_directory/avr-libc/$avr_file")) $core[] = array("filename" => "avr-libc/$avr_file", "content" => file_get_contents("$core_overrd_directory/avr-libc/$avr_file"), "filepath" => "$core_overrd_directory/avr-libc/$avr_file"); else $core[] = array("filename" => "avr-libc/$avr_file", "content" => file_get_contents("$core_files_directory/avr-libc/$avr_file"), "filepath" => "$core_files_directory/avr-libc/$avr_file"); } - } + } - $tmp = $this->extractFiles($core, $temp_directory, $tmp_compiler, $files["core"], "core"); - if($tmp["success"] === false) - return array( "success"=>false, "step"=>5, "message"=>$tmp["message"] ); + $tmp = $this->extractFiles($core, $temp_directory, $tmp_compiler, $files["core"], "core"); + if ($tmp["success"] === false) + return array("success" => false, "step" => 5, "message" => $tmp["message"]); - return array('success' => true); - } + return array('success' => true); + } - private function handleCompile($compile_directory, &$files_array, $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories, $format, $caching = false, $name_params = null){ + private function handleCompile($compile_directory, &$files_array, $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories, $format, $caching = false, $name_params = null) + { - //Add any include directories needed - if (pathinfo($compile_directory, PATHINFO_BASENAME) !== "files") - $include_directories .= " -I$compile_directory "; + //Add any include directories needed + if (pathinfo($compile_directory, PATHINFO_BASENAME) !== "files") + $include_directories .= " -I$compile_directory "; - if(file_exists("$compile_directory/utility")) - $include_directories .= " -I$compile_directory/utility "; + if (file_exists("$compile_directory/utility")) + $include_directories .= " -I$compile_directory/utility "; - if (file_exists("$compile_directory/avr-libc")) - $include_directories .= " -I$compile_directory/avr-libc "; + if (file_exists("$compile_directory/avr-libc")) + $include_directories .= " -I$compile_directory/avr-libc "; - //Call doCompile, which will do the actual compilation. - $compile_res = $this->doCompile($compiler_config, $files_array, $compile_directory, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories, $format, $caching, $name_params); + //Call doCompile, which will do the actual compilation. + $compile_res = $this->doCompile($compiler_config, $files_array, $compile_directory, $CC, $CFLAGS, $CPP, $CPPFLAGS, $AS, $ASFLAGS, $CLANG, $CLANG_FLAGS, $core_includes, $target_arch, $clang_target_arch, $include_directories, $format, $caching, $name_params); - if($compile_res['success']) - return array("success" => true); + if ($compile_res['success']) + return array("success" => true); - return $compile_res; - } + return $compile_res; + } - private function doAutocomplete($ARDUINO_CORES_DIR, $compiler_config, $compile_directory, $CC, $CFLAGS, $CPP, $CPPFLAGS, $core_includes, $target_arch, $include_directories, $autocompletionDir, $PYTHON, $AUTOCOMPLETER){ + private function doAutocomplete($ARDUINO_CORES_DIR, $compiler_config, $compile_directory, $CC, $CFLAGS, $CPP, $CPPFLAGS, $core_includes, $target_arch, $include_directories, $autocompletionDir, $PYTHON, $AUTOCOMPLETER) + { - $file = $compile_directory . "/" . $compiler_config["autocmpfile"]; + $file = $compile_directory."/".$compiler_config["autocmpfile"]; - $filename = pathinfo($file, PATHINFO_DIRNAME) . "/" . pathinfo($file, PATHINFO_FILENAME); + $filename = pathinfo($file, PATHINFO_DIRNAME)."/".pathinfo($file, PATHINFO_FILENAME); $ext = pathinfo($file, PATHINFO_EXTENSION); if (!in_array($ext, array("ino", "c", "cpp", "h", "hpp"))) return array("success" => false, "message" => "Sorry, autocompletion is only supported for .ino, .c, .cpp or .h files."); - if ($ext == "ino"){ + if ($ext == "ino") + { $ext = "cpp"; } $compiler_config["autocmpfile"] = "$filename.$ext"; @@ -1054,7 +1164,7 @@ private function doAutocomplete($ARDUINO_CORES_DIR, $compiler_config, $compile_d // Set the PYTHONPATH environment variable here, instead of setting a global variable in // every machine the compiler runs on. $SET_PYTHONPATH = "export PYTHONPATH=\"$ARDUINO_CORES_DIR/clang/v3_5/bindings/python:\$PYTHONPATH\""; - $result = exec("$SET_PYTHONPATH && $PYTHON $AUTOCOMPLETER " . $compiler_config["autocmpmaxresults"] . " $compile_directory/autocc.json", $output, $retval); + $result = exec("$SET_PYTHONPATH && $PYTHON $AUTOCOMPLETER ".$compiler_config["autocmpmaxresults"]." $compile_directory/autocc.json", $output, $retval); $exec_time = microtime(true) - $time; @@ -1068,11 +1178,13 @@ private function doAutocomplete($ARDUINO_CORES_DIR, $compiler_config, $compile_d return array("success" => true, "retval" => $retval, "message" => "Autocompletion was successful!", "autocomplete" => $command_output, "autocc_exec_time" => $exec_time); } - private function handleAutocompletion($ARDUINO_CORES_DIR, $compile_directory, $include_directories, $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $core_includes, $target_arch, $tmpDir, $autoccDir, $PYTHON, $AUTOCOMPLETER){ + private function handleAutocompletion($ARDUINO_CORES_DIR, $compile_directory, $include_directories, $compiler_config, $CC, $CFLAGS, $CPP, $CPPFLAGS, $core_includes, $target_arch, $tmpDir, $autoccDir, $PYTHON, $AUTOCOMPLETER) + { $make_dir_success = @mkdir("$tmpDir/$autoccDir", 0777, true); - if (!$make_dir_success && !is_dir("$tmpDir/$autoccDir")) { - usleep(rand( 5000 , 10000 )); + if (!$make_dir_success && !is_dir("$tmpDir/$autoccDir")) + { + usleep(rand(5000, 10000)); $make_dir_success = @mkdir("$tmpDir/$autoccDir", 0777, true); } if (!$make_dir_success && !is_dir("$tmpDir/$autoccDir")) @@ -1085,193 +1197,233 @@ private function handleAutocompletion($ARDUINO_CORES_DIR, $compile_directory, $i return $compile_res; } - private function getClangErrorFileList ($clang_output) { - /** - * Clang's output processing - */ - // Get all the 'filename.extension:line' elements. Include only those followed by an 'error' statement. - $tag_free_content = strip_tags($clang_output); // Remove color tags (as many as possible). - - $clang_matches = preg_split('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $tag_free_content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); - - $elements = array(); - foreach ($clang_matches as $key => $val ) { - if (preg_match('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $val) - && array_key_exists($key + 1, $clang_matches) - && (strpos($clang_matches[$key +1 ],"error:") !== false - || strpos($clang_matches[$key +1 ],"note:") !== false - || strpos($clang_matches[$key +1 ],"in asm") !== false - || strpos($clang_matches[$key],"in asm") !== false)) { - if (strpos($val, "In file included from ") !== false) - $val = str_replace("In file included from ", "", $val); - $val = str_replace("In file included from ", "", $val); - $elements[] = $val; - } - } - - // Split the elements from above and get an associative array structure of [filename => lines] - $clang_elements = array(); - foreach ($elements as $element) { - - // The first part is filename.extension, the second represents the line, - // and the third one is the column number (not used for now). - $split = explode(':', $element); - - if (!array_key_exists($split[0], $clang_elements)) { - $clang_elements[$split[0]] = array(); - $clang_elements[$split[0]][] = $split[1]; - continue; - } - $clang_elements[$split[0]][] = $split[1]; - } - return $clang_elements; - } - - private function getGccErrorFileList ($avr_output) { - /** - * Avr gcc's output processing - */ - // Get all 'filename.extension:line' elements. - // Note that avr-gcc output only includes filenames and lines in error reporting, not collumns. - preg_match_all('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $avr_output, $gcc_matches, PREG_PATTERN_ORDER); - - $gcc_elements = array(); - foreach ($gcc_matches[0] as $element) { - - // The first part is filename.extension, the second represents the line. - $split = explode(':', $element); - if (!array_key_exists($split[0], $gcc_elements)) { - $gcc_elements[$split[0]] = array(); - $gcc_elements[$split[0]][] = $split[1]; - continue; - } - $gcc_elements[$split[0]][] = $split[1]; - } - return $gcc_elements; - } - - private function cleanUpClangOutput ($clang_output, $compiler_config, $option) { - - $content_line_array = explode("\n", $clang_output); - - $header = ""; - $body = ""; - $final = ""; - $header_found = false; - $libFound = false; - $coreFound = false; - $asmFound = false; - - foreach ($content_line_array as $key => $line) { - - if ((strpos($line, "In file included from") !== false - && preg_match('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $line)) - || (preg_match('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $line) - && strpos($line, "error:") !== false)) { - - if ($header_found === false) { - if (($option == "non_asm" && preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) - || strpos($header, $compiler_config["arduino_cores_dir"]) !== false - || (array_key_exists("external_core_files", $compiler_config) - && strpos($header, $compiler_config["external_core_files"]) !== false)) - || ($option == "asm" - && (strpos($header, "in asm") !== false - || strpos($body, "in asm") !== false))) { - - if (preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) && $libFound === false && $option != "asm") { - $this->compiler_logger->addInfo($this->logger_id . " - Clang reports library issue."); - $libFound = true; - } - if ((strpos($header, $compiler_config["arduino_cores_dir"]) !== false - || (array_key_exists("external_core_files", $compiler_config) - && strpos($header, $compiler_config["external_core_files"]) !== false)) - && $coreFound === false && $option != "asm") { - $this->compiler_logger->addInfo($this->logger_id . " - Clang reports core issue."); - $coreFound = true; - } - if ((strpos($header, "in asm") !== false || strpos($body, "in asm") !== false) && $asmFound === false && $option == "asm") { - $this->compiler_logger->addInfo($this->logger_id . " - Clang reports assembly issue."); - $asmFound = true; - } - $header = ""; - $body = ""; - } - - if ($header != "") { - if (strpos($header, "") == 0) - $header = substr_replace($header, '', 0, 11); - if (array_key_exists($key + 1, $content_line_array) - && strpos($content_line_array[$key + 1], "") == 0) - $body = $body . ""; - $final .= $header ."\n"; - $final .= $body . "\n"; - $header = ""; - $body = ""; - } - } - - $header .= $line . "\n"; - $header_found = true; - continue; - } - - if (!array_key_exists($key + 1, $content_line_array)) { - if ((!preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) - && strpos($header, $compiler_config["arduino_cores_dir"]) === false - && (array_key_exists("external_core_files", $compiler_config) - && strpos($header, $compiler_config["external_core_files"]) === false) - && $option == "non_asm") - || ($option == "asm" - && strpos($header, "in asm") === false - && strpos($body, "in asm") === false)) { - if ($header != "") { - if (strpos($header, "") == 0) - $header = substr_replace($header, '', 0, 11); - $final .= $header ."\n"; - $final .= $body . "\n"; - } - }else { - if (preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) && $libFound === false && $option != "asm") { - $this->compiler_logger->addInfo($this->logger_id . " - Clang reports library issue."); - } - if ((strpos($header, $compiler_config["arduino_cores_dir"]) !== false - || (array_key_exists("external_core_files", $compiler_config) - && strpos($header, $compiler_config["external_core_files"]) !== false)) - && $coreFound === false && $option != "asm") { - $this->compiler_logger->addInfo($this->logger_id . " - Clang reports core issue."); - } - if ((strpos($header, "in asm") !== false || strpos($body, "in asm") !== false) && $asmFound === false && $option == "asm") { - $this->compiler_logger->addInfo($this->logger_id . " - Clang reports assembly issue."); - } - } - } - - $header_found = false; - $body .= $line . "\n"; - - } - - return $final; - } - - private function pathRemover ($output, $compiler_config) { - - // Remove any instance of "compiler.RANDOM/files/" folder name from the text - $modified = str_replace($compiler_config["compiler_dir"] . "/files/", '', $output); - - // Remove any remaining instance of "compiler.RANDOM/" folder name from the text. - $modified = str_replace($compiler_config["compiler_dir"] . "/", '', $modified); - - // Remove any instance of codebender arduino core files folder name from the text - $modified = str_replace($compiler_config["arduino_cores_dir"] . "/v105/", '', $modified); - - // Remove any instance of codebender external core file folder name from the text - if (isset($compiler_config["external_core_files"]) && $compiler_config["external_core_files"] != "") { - $modified = str_replace($compiler_config["external_core_files"], '', $modified); - $modified = str_replace("/override_cores/", '', $modified); - } - - return $modified; - } + private function getClangErrorFileList($clang_output) + { + /** + * Clang's output processing + */ + // Get all the 'filename.extension:line' elements. Include only those followed by an 'error' statement. + $tag_free_content = strip_tags($clang_output); // Remove color tags (as many as possible). + + $clang_matches = preg_split('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $tag_free_content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); + + $elements = array(); + foreach ($clang_matches as $key => $val) + { + if (preg_match('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $val) + && array_key_exists($key + 1, $clang_matches) + && (strpos($clang_matches[$key + 1], "error:") !== false + || strpos($clang_matches[$key + 1], "note:") !== false + || strpos($clang_matches[$key + 1], "in asm") !== false + || strpos($clang_matches[$key], "in asm") !== false) + ) + { + if (strpos($val, "In file included from ") !== false) + $val = str_replace("In file included from ", "", $val); + $val = str_replace("In file included from ", "", $val); + $elements[] = $val; + } + } + + // Split the elements from above and get an associative array structure of [filename => lines] + $clang_elements = array(); + foreach ($elements as $element) + { + + // The first part is filename.extension, the second represents the line, + // and the third one is the column number (not used for now). + $split = explode(':', $element); + + if (!array_key_exists($split[0], $clang_elements)) + { + $clang_elements[$split[0]] = array(); + $clang_elements[$split[0]][] = $split[1]; + continue; + } + $clang_elements[$split[0]][] = $split[1]; + } + return $clang_elements; + } + + private function getGccErrorFileList($avr_output) + { + /** + * Avr gcc's output processing + */ + // Get all 'filename.extension:line' elements. + // Note that avr-gcc output only includes filenames and lines in error reporting, not collumns. + preg_match_all('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $avr_output, $gcc_matches, PREG_PATTERN_ORDER); + + $gcc_elements = array(); + foreach ($gcc_matches[0] as $element) + { + + // The first part is filename.extension, the second represents the line. + $split = explode(':', $element); + if (!array_key_exists($split[0], $gcc_elements)) + { + $gcc_elements[$split[0]] = array(); + $gcc_elements[$split[0]][] = $split[1]; + continue; + } + $gcc_elements[$split[0]][] = $split[1]; + } + return $gcc_elements; + } + + private function cleanUpClangOutput($clang_output, $compiler_config, $option) + { + + $content_line_array = explode("\n", $clang_output); + + $header = ""; + $body = ""; + $final = ""; + $header_found = false; + $libFound = false; + $coreFound = false; + $asmFound = false; + + foreach ($content_line_array as $key => $line) + { + + if ((strpos($line, "In file included from") !== false + && preg_match('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $line)) + || (preg_match('/([\w*\s*(!@#$%^&*()-+;\'{}\[\])*]+\.\w+:\d+:[\d+:]?)/', $line) + && strpos($line, "error:") !== false) + ) + { + + if ($header_found === false) + { + if (($option == "non_asm" && preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) + || strpos($header, $compiler_config["arduino_cores_dir"]) !== false + || (array_key_exists("external_core_files", $compiler_config) + && strpos($header, $compiler_config["external_core_files"]) !== false)) + || ($option == "asm" + && (strpos($header, "in asm") !== false + || strpos($body, "in asm") !== false)) + ) + { + + if (preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) && $libFound === false && $option != "asm") + { + $this->compiler_logger->addInfo($this->logger_id." - Clang reports library issue."); + $libFound = true; + } + if ((strpos($header, $compiler_config["arduino_cores_dir"]) !== false + || (array_key_exists("external_core_files", $compiler_config) + && strpos($header, $compiler_config["external_core_files"]) !== false)) + && $coreFound === false && $option != "asm" + ) + { + $this->compiler_logger->addInfo($this->logger_id." - Clang reports core issue."); + $coreFound = true; + } + if ((strpos($header, "in asm") !== false || strpos($body, "in asm") !== false) && $asmFound === false && $option == "asm") + { + $this->compiler_logger->addInfo($this->logger_id." - Clang reports assembly issue."); + $asmFound = true; + } + $header = ""; + $body = ""; + } + + if ($header != "") + { + if (strpos($header, "") == 0) + $header = substr_replace($header, '', 0, 11); + if (array_key_exists($key + 1, $content_line_array) + && strpos($content_line_array[$key + 1], "") == 0 + ) + $body = $body.""; + $final .= $header."\n"; + $final .= $body."\n"; + $header = ""; + $body = ""; + } + } + + $header .= $line."\n"; + $header_found = true; + continue; + } + + if (!array_key_exists($key + 1, $content_line_array)) + { + if ((!preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) + && strpos($header, $compiler_config["arduino_cores_dir"]) === false + && (array_key_exists("external_core_files", $compiler_config) + && strpos($header, $compiler_config["external_core_files"]) === false) + && $option == "non_asm") + || ($option == "asm" + && strpos($header, "in asm") === false + && strpos($body, "in asm") === false) + ) + { + if ($header != "") + { + if (strpos($header, "") == 0) + $header = substr_replace($header, '', 0, 11); + $final .= $header."\n"; + $final .= $body."\n"; + } + } + else + { + if (preg_match('/(\/compiler\.\w+\/libraries\/)/', $header) && $libFound === false && $option != "asm") + { + $this->compiler_logger->addInfo($this->logger_id." - Clang reports library issue."); + } + if ((strpos($header, $compiler_config["arduino_cores_dir"]) !== false + || (array_key_exists("external_core_files", $compiler_config) + && strpos($header, $compiler_config["external_core_files"]) !== false)) + && $coreFound === false && $option != "asm" + ) + { + $this->compiler_logger->addInfo($this->logger_id." - Clang reports core issue."); + } + if ((strpos($header, "in asm") !== false || strpos($body, "in asm") !== false) && $asmFound === false && $option == "asm") + { + $this->compiler_logger->addInfo($this->logger_id." - Clang reports assembly issue."); + } + } + } + + $header_found = false; + $body .= $line."\n"; + + } + + return $final; + } + + private function pathRemover($output, $compiler_config) + { + + // Remove any instance of "compiler.RANDOM/files/" folder name from the text, add (sketch file) info text + $modified = str_replace($compiler_config["compiler_dir"]."/files/", '(sketch file) ', $output); + + // Remove any remaining instance of "compiler.RANDOM/" folder name from the text. + $modified = str_replace($compiler_config["compiler_dir"]."/", '', $modified); + + // Replace userId_cb_personal_lib prefix from personal libraries errors with a (personal library file) info text. + $modified = preg_replace('/libraries\/\d+_cb_personal_lib_/', '(personal library file) ', $modified); + + // Replace libraries/ prefix from personal libraries errors with a (personal library file) info text. + $modified = str_replace('libraries/', '(library file) ', $modified); + + // Remove any instance of codebender arduino core files folder name from the text, add (arduino core file) info text + $modified = str_replace($compiler_config["arduino_cores_dir"]."/v105/", '(arduino core file) ', $modified); + + // Remove any instance of codebender external core file folder name from the text, , add (arduino core file) info text + if (isset($compiler_config["external_core_files"]) && $compiler_config["external_core_files"] != "") + { + $modified = str_replace($compiler_config["external_core_files"], '(arduino core file) ', $modified); + $modified = str_replace("/override_cores/", '(arduino core file) ', $modified); + } + + return $modified; + } } diff --git a/Symfony/src/Codebender/CompilerBundle/Handler/DeletionHandler.php b/Symfony/src/Codebender/CompilerBundle/Handler/DeletionHandler.php new file mode 100644 index 0000000..c8e3d2f --- /dev/null +++ b/Symfony/src/Codebender/CompilerBundle/Handler/DeletionHandler.php @@ -0,0 +1,116 @@ +objectCacheDirectory = $objectFilesDirectory; + } + + function deleteAllObjects() + { + $fileCount = 0; + $notDeletedFiles = ''; + $deletionStats = array('success_dot_a' => 0, + 'failure_dot_a' => 0, + 'success_dot_o' => 0, + 'failure_dot_o' => 0, + 'success_dot_d' => 0, + 'failure_dot_d' => 0, + 'success_dot_LOCK' => 0, + 'failure_dot_LOCK' => 0); + + if ($handle = @opendir($this->objectCacheDirectory)) { + + while (false !== ($entry = readdir($handle))) { + if ($entry == '.' || $entry == '..' || $entry != '.DS_Store') { + continue; + } + $fileCount++; + $extension = pathinfo($entry, PATHINFO_EXTENSION); + + if (!in_array($extension, array('a', 'o', 'd', 'LOCK'))) { + continue; + } + + if (@unlink($this->objectCacheDirectory . '/' . $entry) === false) { + $deletionStats['failure_dot_$extension']++; + $notDeletedFiles .= $entry . "\n"; + continue; + } + + $deletionStats['success_dot_' . $extension]++; + } + closedir($handle); + + return array( + 'success' => true, + 'fileCount' => $fileCount, + 'notDeletedFiles' => $notDeletedFiles, + 'deletionStats' => $deletionStats + ); + } + + return array('success' => false); + } + + function deleteSpecificObjects($option, $cachedObjectToDelete) + { + if ($option == 'core') { + $cachedObjectToDelete = str_replace(':', '_', $cachedObjectToDelete); + } + + $deletedFiles = ''; + $notDeletedFiles = ''; + + if ($handle = @opendir($this->objectCacheDirectory)) { + + while (false !== ($entry = readdir($handle))) { + + if ($entry == '.' || $entry == '..' || $entry == '.DS_Store') { + continue; + } + + if ($option == 'library' && strpos($entry, '______' . $cachedObjectToDelete . '_______') === false) { + continue; + } + + if ($option == 'core' && strpos($entry, '_' . $cachedObjectToDelete . '_') === false) { + continue; + } + + + if (@unlink($this->objectCacheDirectory . '/' . $entry) === false) { + $notDeletedFiles .= $entry."\n"; + continue; + } + + $deletedFiles .= $entry . "\n"; + + } + closedir($handle); + + return array('success' => true, 'deletedFiles' => $deletedFiles, 'notDeletedFiles' => $notDeletedFiles); + } + + return array('success' => false); + } +} diff --git a/Symfony/src/Codebender/CompilerBundle/Handler/MCUHandler.php b/Symfony/src/Codebender/CompilerBundle/Handler/MCUHandler.php index e3b542a..5fad6a8 100644 --- a/Symfony/src/Codebender/CompilerBundle/Handler/MCUHandler.php +++ b/Symfony/src/Codebender/CompilerBundle/Handler/MCUHandler.php @@ -1,20 +1,20 @@ . - -\author Dimitrios Christidis -\author Vasilis Georgitzikis - -\copyright (c) 2012, The Codebender Development Team -\copyright Licensed under the Simplified BSD License + * \file + * \brief MCU macros for Clang. + * + * When compiling source code for ATMEL AVR, one must specify the MCU type + * (avr-gcc's -mmcu flag). This defines a macro that is used for conditional + * compilation. Clang has no such flag, and thus the macro has to be predefined + * by hand. + * + * See . + * + * \author Dimitrios Christidis + * \author Vasilis Georgitzikis + * + * \copyright (c) 2012, The Codebender Development Team + * \copyright Licensed under the Simplified BSD License */ namespace Codebender\CompilerBundle\Handler; diff --git a/Symfony/src/Codebender/CompilerBundle/Handler/PostprocessingHandler.php b/Symfony/src/Codebender/CompilerBundle/Handler/PostprocessingHandler.php index ca83a86..afbe798 100644 --- a/Symfony/src/Codebender/CompilerBundle/Handler/PostprocessingHandler.php +++ b/Symfony/src/Codebender/CompilerBundle/Handler/PostprocessingHandler.php @@ -13,21 +13,21 @@ class PostprocessingHandler { /** - \brief Converts text with ANSI color codes to HTML. - - \param string $text The string to convert. - \return A string with HTML tags. - - Takes a string with ANSI color codes and converts them to HTML tags. Can be - useful for displaying the output of terminal commands on a web page. Handles - codes that modify the color (foreground and background) as well as the format - (bold, italics, underline and strikethrough). Other codes are ignored. - - An ANSI escape sequence begins with the characters ^[ (hex 0x1B) and - [, and ends with m. The color code is placed in between. Multiple - color codes can be included, separated by semicolon. + * \brief Converts text with ANSI color codes to HTML. + * + * \param string $text The string to convert. + * \return A string with HTML tags. + * + * Takes a string with ANSI color codes and converts them to HTML tags. Can be + * useful for displaying the output of terminal commands on a web page. Handles + * codes that modify the color (foreground and background) as well as the format + * (bold, italics, underline and strikethrough). Other codes are ignored. + * + * An ANSI escape sequence begins with the characters ^[ (hex 0x1B) and + * [, and ends with m. The color code is placed in between. Multiple + * color codes can be included, separated by semicolon. */ - function ansi_to_html($text) + function convertANSItoHTML($text) { $FORMAT = array( 0 => NULL, // reset modes to default @@ -107,7 +107,7 @@ function ansi_to_html($text) array_push($stack, ""); break; default: - error_log(__FUNCTION__."(): Unhandled ANSI code '$mode' in ".__FILE__); + error_log(__FUNCTION__."(): Unhandled ANSI code '$mode'"); break; } } diff --git a/Symfony/src/Codebender/CompilerBundle/Handler/PreprocessingHandler.php b/Symfony/src/Codebender/CompilerBundle/Handler/PreprocessingHandler.php index a7d327d..5d72597 100644 --- a/Symfony/src/Codebender/CompilerBundle/Handler/PreprocessingHandler.php +++ b/Symfony/src/Codebender/CompilerBundle/Handler/PreprocessingHandler.php @@ -13,253 +13,283 @@ class PreprocessingHandler { /** - \brief The following functions generate valid C++ code from Arduino source code. - - Arduino source code files are simplified C++ files. Thus, some preprocessing has - to be done to convert them to valid C++ code for the compiler to read. Some of - these "simplifications" include: - - lack of a main() function - - lack of function prototypes - - A skeleton file is provided in the Arduino core files that contains a - main() function. Its contents have to be linked to the output file later. - The prototypes of the functions defined in the input file should be added - above the code. This is required to avoid compiler errors regarding undefined - functions. - - The programmer is not aware of this modifications to his code. In case of a - compiler error, the line numbering would be wrong. To avoid this issue, a - \#line preprocessor directive is used. Thus it is ensured that the line - numbering in the output file will be the same as the input file. - - A regular expression is used to match function definitions in the input file. - Consequently this process will never be as sophisticated as a lexical analyzer. - Thus, some valid constructs cannot be matched. These include: - - definitions that are split across multiple lines - - definitions for variadic functions - - typedefs for the return value or the parameters - - pointers to functions - - arrays, structs, and unions + * \brief The following functions generate valid C++ code from Arduino source code. + * + * Arduino source code files are simplified C++ files. Thus, some preprocessing has + * to be done to convert them to valid C++ code for the compiler to read. Some of + * these "simplifications" include: + * - lack of a main() function + * - lack of function prototypes + * + * A skeleton file is provided in the Arduino core files that contains a + * main() function. Its contents have to be linked to the output file later. + * The prototypes of the functions defined in the input file should be added + * above the code. This is required to avoid compiler errors regarding undefined + * functions. + * + * The programmer is not aware of this modifications to his code. In case of a + * compiler error, the line numbering would be wrong. To avoid this issue, a + * \#line preprocessor directive is used. Thus it is ensured that the line + * numbering in the output file will be the same as the input file. + * + * A regular expression is used to match function definitions in the input file. + * Consequently this process will never be as sophisticated as a lexical analyzer. + * Thus, some valid constructs cannot be matched. These include: + * - definitions that are split across multiple lines + * - definitions for variadic functions + * - typedefs for the return value or the parameters + * - pointers to functions + * - arrays, structs, and unions */ - /** - \param string $code The original code of the sketch - \return string A copy of the code with no comments, single- or double- quoted strings - or pre-processor directives - */ - function remove_comments_directives_quotes($code) - { - // Use a copy of the code and strip comments, pre-processor directives, single- and double-quoted strings - - $regex = "/(\'.\')|(\"(?:[^\"\\\\]|\\\\.)*\")|(\/\/.*?$)|(\/\*[^*]*(?:\*(?!\/)[^*]*)*\*\/)|(^\s*\#.*?$)/m"; - - // Replace every match of the regular expression with a whitespace - - $return_code = preg_replace($regex, " ", $code); - - return $return_code; - } - - /** - \param string $code The code returned from remove_comments_directives_quotes function - \return string The input code having all top level braces collapsed - */ - function empty_braces($code) - { - // For every line of the code remove all the contents of top level braces - - $nesting = 0; - $start = 0; - $return_code = ""; - // Use the code as an array of characters - for ($i=0; $iremove_comments_directives_quotes($code); - // Remove any code between all top level braces - $empty_braces_code = $this->empty_braces($no_comms_code); - // Find already existing prototypes - $existing_prototypes = $this->find_existing_prototypes($empty_braces_code); - // Generate prototypes that do not already exist - $function_prototypes = $this->generate_prototypes($empty_braces_code, $existing_prototypes); - // Find the right place to insert the function prototypes (after any preprocessor directives, comments, before any function declaration) - $insertion_position = $this->insertion_position($code); - - $new_code = ""; + function convertInoToCpp($code, $filename = null) + { + // Remove comments, preprocessor directives, single- and double- quotes + $no_comms_code = $this->removeCommentsDirectivesQuotes($code); + // Remove any code between all top level braces + $empty_braces_code = $this->emptyBraces($no_comms_code); + // Find already existing prototypes + $existing_prototypes = $this->findExistingPrototypes($empty_braces_code); + // Generate prototypes that do not already exist + $function_prototypes = $this->generatePrototypes($empty_braces_code, $existing_prototypes); + // Find the right place to insert the function prototypes (after any preprocessor directives, comments, + // before any function declaration) + $insertion_position = $this->insertionPosition($code); + + $new_code = "#line 1\n"; // Add a preprocessor directive for line numbering. - if ($filename) + if ($filename) { $new_code .= "#line 1 \"$filename\"\n"; - else - $new_code .= "#line 1\n"; - // Build the new code for the cpp file that will eventually be compiled - $new_code .= $this->build_code($code, $function_prototypes, $insertion_position); + } - return $new_code; + // Build the new code for the cpp file that will eventually be compiled + $new_code .= $this->buildCode($code, $function_prototypes, $insertion_position); - } + return $new_code; + } /** - \brief Decodes and performs validation checks on input data. - - \param string $request The JSON-encoded compile request. - \return The value encoded in JSON in appropriate PHP type or NULL. + * \brief Decodes and performs validation checks on input data. + * + * \param string $request The JSON-encoded compile request. + * \return The value encoded in JSON in appropriate PHP type or null. */ - function validate_input($request) + function validateInput($request) { $request = json_decode($request, true); // Request must be successfully decoded. - if ($request === NULL) - return NULL; + if ($request === null) + return null; // Request must contain certain entities. if (!(array_key_exists("format", $request) && array_key_exists("version", $request) @@ -272,23 +302,26 @@ function validate_input($request) && array_key_exists("core", $request["build"]) && is_array($request["files"])) ) - return NULL; + return null; // Leonardo-specific flags. if (array_key_exists("variant", $request["build"]) && $request["build"]["variant"] == "leonardo") if (!(array_key_exists("vid", $request["build"]) && array_key_exists("pid", $request["build"])) ) - return NULL; + return null; // Values used as command-line arguments may not contain any special // characters. This is a serious security risk. - $values = array("version", "mcu", "f_cpu", "core", "vid", "pid"); - if (array_key_exists("variant", $request["build"])) + $values = array("version", "mcu", "f_cpu", "core", "vid", "pid"); + if (array_key_exists("variant", $request["build"])) { $values[] = "variant"; - foreach ($values as $i) - if (isset($request["build"][$i]) && escapeshellcmd($request["build"][$i]) != $request["build"][$i]) - return NULL; + } + foreach ($values as $i) { + if (isset($request["build"][$i]) && escapeshellcmd($request["build"][$i]) != $request["build"][$i]) { + return null; + } + } // Request is valid. return $request; diff --git a/Symfony/src/Codebender/CompilerBundle/Handler/UtilityHandler.php b/Symfony/src/Codebender/CompilerBundle/Handler/UtilityHandler.php index 3e6c0db..f674b6e 100644 --- a/Symfony/src/Codebender/CompilerBundle/Handler/UtilityHandler.php +++ b/Symfony/src/Codebender/CompilerBundle/Handler/UtilityHandler.php @@ -13,51 +13,51 @@ class UtilityHandler { /** - \brief Extracts the files included in a compile request. - - \param string $directory The directory to extract the files to. - \param array $request_files The files structure, as taken from the JSON request. - \return A list of files or a reply message in case of error. - - Takes the files structure from a compile request and creates each file in a - specified directory. If requested, it may create additional directories and - have the files placed inside them accordingly. - - Also creates a new structure where each key is the file extension and the - associated value is an array containing the absolute paths of the file, minus - the extension. - - In case of error, the return value is an array that has a key success - and contains the response to be sent back to the user. + * \brief Extracts the files included in a compile request. + * + * \param string $directory The directory to extract the files to. + * \param array $request_files The files structure, as taken from the JSON request. + * \return A list of files or a reply message in case of error. + * + * Takes the files structure from a compile request and creates each file in a + * specified directory. If requested, it may create additional directories and + * have the files placed inside them accordingly. + * + * Also creates a new structure where each key is the file extension and the + * associated value is an array containing the absolute paths of the file, minus + * the extension. + * + * In case of error, the return value is an array that has a key success + * and contains the response to be sent back to the user. */ - function extract_files($directory, $request_files, $lib_extraction) + function extractFiles($directory, $request_files, $lib_extraction) { // File extensions used by Arduino projects. They are put in a string, // separated by "|" to be used in regular expressions. They are also // used as keys in an array that will contain the paths of all the // extracted files. - $EXTENSIONS = array("c", "cpp", "h", "inc", "ino", "o", "S"); + $allowedExtensions = array("c", "cpp", "h", "inc", "ino", "o", "S"); $files = array(); - foreach ($EXTENSIONS as $ext) + foreach ($allowedExtensions as $ext) $files[$ext] = array(); - $EXTENSIONS = implode("|", $EXTENSIONS); + $allowedExtensions = implode("|", $allowedExtensions); // Matches filename that end with an appropriate extension. The name // without the extension is stored in registerd 1, the extension itself // in register 2. // // Examples: foo.c bar.cpp - $REGEX = "/(.*)\.($EXTENSIONS)$/"; + $extensionsRegex = "/(.*)\.($allowedExtensions)$/"; - if(!file_exists($directory)) - mkdir($directory, 0777, true); + if (!file_exists($directory)) + mkdir($directory, 0777, true); foreach ($request_files as $file) { $filename = $file["filename"]; $content = $file["content"]; - $ignore = false; + $ignore = false; - $failure_response = array( + $failureResponse = array( "success" => false, "step" => 1, "message" => "Failed to extract file '$filename'."); @@ -66,33 +66,33 @@ function extract_files($directory, $request_files, $lib_extraction) // serious security risk. $directories = explode("/", "$directory/$filename"); if (in_array("..", $directories)) - return $failure_response; + return $failureResponse; if (strpos($filename, DIRECTORY_SEPARATOR)) { $new_directory = pathinfo($filename, PATHINFO_DIRNAME); - if (($lib_extraction === true) && ($new_directory !== "utility")) - $ignore = true; - if (!file_exists("$directory/$new_directory")) - mkdir("$directory/$new_directory", 0777, true); - // There is no reason to check whether mkdir() - // succeeded, given that the call to - // file_put_contents() that follows would fail - // as well. + if (($lib_extraction === true) && ($new_directory !== "utility")) + $ignore = true; + if (!file_exists("$directory/$new_directory")) + mkdir("$directory/$new_directory", 0777, true); + // There is no reason to check whether mkdir() + // succeeded, given that the call to + // file_put_contents() that follows would fail + // as well. } if (file_put_contents("$directory/$filename", $content) === false) - return $failure_response; + return $failureResponse; - if ($ignore) - continue; + if ($ignore) + continue; - if (preg_match($REGEX, $filename, $matches)) + if (preg_match($extensionsRegex, $filename, $matches)) $files[$matches[2]][] = "$directory/$matches[1]"; else - error_log(__FUNCTION__."(): Unhandled file extension '$filename' in ".__FILE__); + error_log(__FUNCTION__."(): Unhandled file extension '$filename'"); } // All files were extracted successfully. @@ -100,11 +100,11 @@ function extract_files($directory, $request_files, $lib_extraction) } /** - \brief Searches for files with specific extensions in a directory. - - \param string $directory The directory to search for files. - \param mixed $extensions An array of strings, the extensions to look for. - \return A list of files that have the appropriate extension. + * \brief Searches for files with specific extensions in a directory. + * + * \param string $directory The directory to search for files. + * \param mixed $extensions An array of strings, the extensions to look for. + * \return A list of files that have the appropriate extension. */ function get_files_by_extension($directory, $extensions) { @@ -120,22 +120,22 @@ function get_files_by_extension($directory, $extensions) } /** - \brief Executes a command and displays the command itself and its output. - - \param string $command The command to be executed. - - Simplifies the creation and debugging of pages that rely on multiple external - programs by "emulating" the execution of the requested command in a terminal - emulator. Can be useful during early stages of development. Replace with - exec() afterwards. - - To perform the command execution, passthru() is used. The string - 2\>&1 is appended to the command to ensure messages sent to standard - error are not lost. - - \warning It is not possible to redirect the standard error output to a file. + * \brief Executes a command and displays the command itself and its output. + * + * \param string $command The command to be executed. + * + * Simplifies the creation and debugging of pages that rely on multiple external + * programs by "emulating" the execution of the requested command in a terminal + * emulator. Can be useful during early stages of development. Replace with + * exec() afterwards. + * + * To perform the command execution, passthru() is used. The string + * 2\>&1 is appended to the command to ensure messages sent to standard + * error are not lost. + * + * \warning It is not possible to redirect the standard error output to a file. */ - function debug_exec($command, /** @noinspection PhpUnusedParameterInspection */ + function execWithDebugging($command, /** @noinspection PhpUnusedParameterInspection */ &$output, /** @noinspection PhpUnusedParameterInspection */ &$retval) { diff --git a/Symfony/src/Codebender/CompilerBundle/Resources/config/routing.yml b/Symfony/src/Codebender/CompilerBundle/Resources/config/routing.yml index e4ae4bd..bb0f875 100644 --- a/Symfony/src/Codebender/CompilerBundle/Resources/config/routing.yml +++ b/Symfony/src/Codebender/CompilerBundle/Resources/config/routing.yml @@ -15,10 +15,9 @@ codebender_compiler_delete_all: defaults: { _controller: CodebenderCompilerBundle:Default:deleteAllObjects } codebender_compiler_delete_specific: - pattern: /{authorizationKey}/{version}/delete/{option}/{to_delete} + pattern: /{authorizationKey}/{version}/delete/{option}/{cachedObjectToDelete} defaults: { _controller: CodebenderCompilerBundle:Default:deleteSpecificObjects } - # redirecting the root root: path: / diff --git a/Symfony/src/Codebender/CompilerBundle/Resources/config/services.yml b/Symfony/src/Codebender/CompilerBundle/Resources/config/services.yml index a529420..675bd9e 100644 --- a/Symfony/src/Codebender/CompilerBundle/Resources/config/services.yml +++ b/Symfony/src/Codebender/CompilerBundle/Resources/config/services.yml @@ -4,6 +4,7 @@ parameters: utility_handler.class: Codebender\CompilerBundle\Handler\UtilityHandler preprocessing_handler.class: Codebender\CompilerBundle\Handler\PreprocessingHandler postprocessing_handler.class: Codebender\CompilerBundle\Handler\PostprocessingHandler + deletion_handler.class: Codebender\CompilerBundle\Handler\DeletionHandler services: # codebender_compiler.example: @@ -18,6 +19,9 @@ services: class: "%preprocessing_handler.class%" postprocessing_handler: class: "%postprocessing_handler.class%" + deletion_handler: + class: "%deletion_handler.class%" + arguments: ["@compiler_logger", "%temp_dir%/%objdir%"] compiler_logger: class: Symfony\Bridge\Monolog\Logger arguments: [cmplr_log] diff --git a/Symfony/src/Codebender/CompilerBundle/Tests/Controller/DefaultControllerFunctionalTest.php b/Symfony/src/Codebender/CompilerBundle/Tests/Controller/DefaultControllerFunctionalTest.php new file mode 100644 index 0000000..560f268 --- /dev/null +++ b/Symfony/src/Codebender/CompilerBundle/Tests/Controller/DefaultControllerFunctionalTest.php @@ -0,0 +1,307 @@ +request('GET', '/status'); + + $this->assertEquals($client->getResponse()->getContent(), '{"success":true,"status":"OK"}'); + + } + + public function testInvalidKey() + { + $client = static::createClient(); + + $client->request('GET', '/inValidKey/v1'); + + $this->assertEquals($client->getResponse()->getContent(), '{"success":false,"step":0,"message":"Invalid authorization key."}'); + + } + + public function testInvalidAPI() + { + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('GET', '/' . $authorizationKey . '/v666'); + + $this->assertEquals($client->getResponse()->getContent(), '{"success":false,"step":0,"message":"Invalid API version."}'); + + } + + public function testInvalidInput() + { + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('GET', '/' . $authorizationKey . '/v1'); + + $this->assertEquals($client->getResponse()->getContent(), '{"success":false,"step":0,"message":"Invalid input."}'); + + } + + public function testBlinkUnoSyntaxCheck() + { + $files = array(array("filename" => "Blink.ino", "content" => "int led = 13;\nvoid setup() {pinMode(led, OUTPUT);}\nvoid loop() {\ndigitalWrite(led, HIGH);\ndelay(1000);\ndigitalWrite(led, LOW);\ndelay(1000);\n}\n")); + $format = "syntax"; + $version = "105"; + $libraries = array(); + $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); + + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response["success"], true); + $this->assertTrue(is_numeric($response["time"])); + + } + + public function testBlinkUnoCompile() + { + $files = array(array("filename" => "Blink.ino", "content" => "\nint led = 13;\nvoid setup() {\npinMode(led, OUTPUT);\n}\nvoid loop() {\ndigitalWrite(led, HIGH);\ndelay(1000);\ndigitalWrite(led, LOW);\ndelay(1000);\n}\n")); + $format = "binary"; + $version = "105"; + $libraries = array(); + $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); + + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response["success"], true); + $this->assertTrue(is_numeric($response["time"])); + $this->assertTrue(is_numeric($response["size"])); + + $objectFilesPath = $client->getContainer()->getParameter('temp_dir') . '/' . $client->getContainer()->getParameter('objdir'); + $coreObjectLibrary = glob("$objectFilesPath/*__v105__hardware__arduino__cores__arduino________atmega328p_16000000_arduino_standard_null_null_______core.a"); + $this->assertTrue(count($coreObjectLibrary) > 0); + } + + public function testBlinkUnoSyntaxCheckError() + { + $files = array(array("filename" => "Blink.ino", "content" => "\nint led = 13\nvoid setup() {\npinMode(led, OUTPUT);\npinMode(led);\n}\nvoid loop() {\ndigitalWrite(led, HIGH);\ndelay(1000);\ndigitalWrite(led, LOW);\ndelay(1000);\n}\n")); + $format = "syntax"; + $version = "105"; + $libraries = array(); + $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); + + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response["success"], false); + $this->assertEquals($response["success"], false); + $this->assertEquals($response["step"], 4); + $this->assertContains("Blink.ino:2:13:", $response["message"]); + $this->assertContains("expected ';' after top level declarator", $response["message"]); + $this->assertContains("no matching function for call to 'pinMode'", $response["message"]); + $this->assertContains("candidate function not viable: requires 2 arguments, but 1 was provided", $response["message"]); + // $this->assertContains("2 errors generated.", $response["message"]); //unfortunately we no longer show how many errors were generated + } + + public function testBlinkUnoCompileError() + { + $files = array(array("filename" => "Blink.ino", "content" => "\nint led = 13\nvoid setup() {\npinMode(led, OUTPUT);\npinMode(led);\n}\nvoid loop() {\ndigitalWrite(led, HIGH);\ndelay(1000);\ndigitalWrite(led, LOW);\n delay(1000);\n}\n")); + $format = "binary"; + $version = "105"; + $libraries = array(); + $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); + + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response["success"], false); + $this->assertEquals($response["step"], 4); + $this->assertContains("Blink.ino:2:13:", $response["message"]); + $this->assertContains("expected ';' after top level declarator", $response["message"]); + $this->assertContains("no matching function for call to 'pinMode'", $response["message"]); + $this->assertContains("candidate function not viable: requires 2 arguments, but 1 was provided", $response["message"]); + // $this->assertContains("2 errors generated.", $response["message"]); //unfortunately we no longer show how many errors were generated + } + + public function testExternalVariant() + { + $files = array(array('filename' => 'Blink.ino', 'content' => "void setup(){}\nvoid loop(){}\n")); + $format = 'binary'; + $version = '105'; + $libraries = array(); + $build = array('mcu' => 'atmega32u4', 'f_cpu' => '8000000', 'core' => 'arduino', 'variant' => 'flora', 'pid' => '0x8004', 'vid' => '0x239A'); + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response['success'], true); + $objectFilesPath = $client->getContainer()->getParameter('temp_dir') . '/' . $client->getContainer()->getParameter('objdir'); + $coreObjectLibrary = glob("$objectFilesPath/*v105__hardware__arduino__cores__arduino________atmega32u4_8000000_arduino_flora_0x239A_0x8004_______core.a"); + + $this->assertTrue(count($coreObjectLibrary) > 0); + } + + public function testExternalCore() + { + $files = array(array('filename' => 'Blink.ino', 'content' => "void setup(){}\nvoid loop(){}\n")); + $format = 'binary'; + $version = '105'; + $libraries = array(); + $build = array('mcu' => 'attiny85', 'f_cpu' => '8000000', 'core' => 'tiny'); + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response['success'], true); + $objectFilesPath = $client->getContainer()->getParameter('temp_dir') . '/' . $client->getContainer()->getParameter('objdir'); + $externalCoresPath = pathinfo($client->getContainer()->getParameter('external_core_files'), PATHINFO_BASENAME); + $coreObjectLibrary = glob("$objectFilesPath/*__{$externalCoresPath}__tiny__cores__tiny________attiny85_8000000_tiny__null_null_______core.a"); + + $this->assertTrue(count($coreObjectLibrary) > 0); + } + + public function testArchiveIsCreated() + { + $files = array(array('filename' => 'Blink.ino', 'content' => "void setup(){}\nvoid loop(){}\n")); + $format = 'binary'; + $version = '105'; + $libraries = array(); + $build = array('mcu' => 'atmega328p', 'f_cpu' => '16000000', 'core' => 'arduino', 'variant' => 'standard'); + $data = json_encode(array('files' => $files, 'archive' => true, 'format' => $format, 'version' => $version, 'libraries' => $libraries, 'build' => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter('authorizationKey'); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + + $this->assertTrue(file_exists($response['archive'])); + } + + public function testCleanedUpLinkerError() + { + $files = array(array('filename' => 'Linker.ino', 'content' => 'void loop() { }')); + $format = 'binary'; + $version = '105'; + $libraries = array(); + $build = array('mcu' => 'atmega328p', 'f_cpu' => '16000000', 'core' => 'arduino', 'variant' => 'standard'); + $data = json_encode(array('files' => $files, 'archive' => true, 'format' => $format, 'version' => $version, 'libraries' => $libraries, 'build' => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter('authorizationKey'); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $expectedLinkerError = "core.a(main.o): In function `main': +main.cpp:(.text.main+0x8): undefined reference to `setup'"; + + $this->assertFalse($response['success']); + $this->assertEquals($expectedLinkerError, $response['message']); + } + + public function testEthernetCompileErrorRemovedLibraryPaths() + { + $files = array(array("filename" => "Blink.ino", "content" => "#include \nvoid setup() {\n}\nvoid loop() {\n}\n")); + $format = "binary"; + $version = "105"; + $libraries = array('PseudoEthernet' => array('files' => array('filename' => 'Ethernet.h', 'content' => "#include \"SPI.h\"\n"))); + $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); + + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response["success"], false); + $this->assertEquals($response["step"], 4); + $this->assertContains('(library file) PseudoEthernet/Ethernet.h:1:10: fatal error: \'SPI.h\' file not found', $response['message']); + } + + public function testEthernetCompileErrorRemovedPersonalLibraryPaths() + { + $files = array(array("filename" => "Blink.ino", "content" => "#include \nvoid setup() {\n}\nvoid loop() {\n}\n")); + $format = "binary"; + $version = "105"; + $libraries = array('4096_cb_personal_lib_PseudoEthernet' => array('files' => array('filename' => 'Ethernet.h', 'content' => "#include \"SPI.h\"\n"))); + $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); + + $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); + + $client = static::createClient(); + + $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); + + $client->request('POST', '/' . $authorizationKey . '/v1', array(), array(), array(), $data); + + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals($response["success"], false); + $this->assertEquals($response["step"], 4); + $this->assertContains('(personal library file) PseudoEthernet/Ethernet.h:1:10: fatal error: \'SPI.h\' file not found', $response['message']); + } + + public function testAutocomplete() + { + $this->markTestIncomplete('No tests for the code completion feature yet.'); + } + + public function testIncorrectInputs() + { + $this->markTestIncomplete('No tests for invalid inputs yet'); + } +} diff --git a/Symfony/src/Codebender/CompilerBundle/Tests/Controller/DefaultControllerTest.php b/Symfony/src/Codebender/CompilerBundle/Tests/Controller/DefaultControllerTest.php deleted file mode 100644 index 2057e10..0000000 --- a/Symfony/src/Codebender/CompilerBundle/Tests/Controller/DefaultControllerTest.php +++ /dev/null @@ -1,160 +0,0 @@ -request('GET', '/status'); - - $this->assertEquals($client->getResponse()->getContent(), '{"success":true,"status":"OK"}'); - - } - - public function testInvalidKey() - { - $client = static::createClient(); - - $client->request('GET', '/inValidKey/v1'); - - $this->assertEquals($client->getResponse()->getContent(), '{"success":false,"step":0,"message":"Invalid authorization key."}'); - - } - - public function testInvalidAPI() - { - $client = static::createClient(); - - $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); - - $client->request('GET', '/'.$authorizationKey.'/v666'); - - $this->assertEquals($client->getResponse()->getContent(), '{"success":false,"step":0,"message":"Invalid API version."}'); - - } - - public function testInvalidInput() - { - $client = static::createClient(); - - $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); - - $client->request('GET', '/'.$authorizationKey.'/v1'); - - $this->assertEquals($client->getResponse()->getContent(), '{"success":false,"step":0,"message":"Invalid input."}'); - - } - - public function testBlinkUnoSyntaxCheck() - { - $files = array(array("filename" => "Blink.ino", "content" => "/*\n Blink\n Turns on an LED on for one second, then off for one second, repeatedly.\n \n This example code is in the public domain.\n *///\n \n// Pin 13 has an LED connected on most Arduino boards.\n// give it a name:\nint led = 13;\n\n// the setup routine runs once when you press reset:\nvoid setup() { \n // initialize the digital pin as an output.\n pinMode(led, OUTPUT); \n}\n\n// the loop routine runs over and over again forever:\nvoid loop() {\n digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)\n delay(1000); // wait for a second\n digitalWrite(led, LOW); // turn the LED off by making the voltage LOW\n delay(1000); // wait for a second\n}\n")); - $format = "syntax"; - $version = "105"; - $libraries = array(); - $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); - - $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); - - $client = static::createClient(); - - $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); - - $client->request('POST', '/'.$authorizationKey.'/v1', array(),array(),array(),$data); - - $response = json_decode($client->getResponse()->getContent(), true); - - $this->assertEquals($response["success"], true); - $this->assertTrue(is_numeric($response["time"])); - - } - - public function testBlinkUnoCompile() - { - $files = array(array("filename" => "Blink.ino", "content" => "/*\n Blink\n Turns on an LED on for one second, then off for one second, repeatedly.\n \n This example code is in the public domain.\n *///\n \n// Pin 13 has an LED connected on most Arduino boards.\n// give it a name:\nint led = 13;\n\n// the setup routine runs once when you press reset:\nvoid setup() { \n // initialize the digital pin as an output.\n pinMode(led, OUTPUT); \n}\n\n// the loop routine runs over and over again forever:\nvoid loop() {\n digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)\n delay(1000); // wait for a second\n digitalWrite(led, LOW); // turn the LED off by making the voltage LOW\n delay(1000); // wait for a second\n}\n")); - $format = "binary"; - $version = "105"; - $libraries = array(); - $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); - - $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); - - $client = static::createClient(); - - $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); - - $client->request('POST', '/'.$authorizationKey.'/v1', array(), array(), array(), $data); - - $response = json_decode($client->getResponse()->getContent(), true); - - $this->assertEquals($response["success"], true); - $this->assertTrue(is_numeric($response["time"])); - $this->assertTrue(is_numeric($response["size"])); - //TODO: Find a way to make this work with both linux and os x -// $this->assertEquals($response["output"], 'DJRkAAyU/wMMlCwEDJSMAAyUjAAMlIwADJSMAAyUowMMlIwADJSMAAyUjAAMlIwADJSMAAyUjAAMlIwADJSMAAyUWQQMlIwADJS+AAyUDAEMlIwADJSMAAyUjAAMlIwADJSMAAyUjAACAAAAACQAJwAqAAAAAAAlACgAKwAAAAAAIwAmACkABAQEBAQEBAQCAgICAgIDAwMDAwMBAgQIECBAgAECBAgQIAECBAgQIAAAAAcAAgEAAAMEBgAAAAAAAAAAAPEBRwIRJB++z+/Y4N6/zb8R4KDgseDi4vzgAsAFkA2SqjGxB9n3EeCq4bHgAcAdkq49sQfh9xDgyOzQ4ATAIpf+AQ6UCwbEPNEHyfcOlK4ADJSOAAyUAAD4lAyUDwaAkQABYeAOlHQFaO5z4IDgkOAOlKEEgJEAAWDgDpR0BWjuc+CA4JDgDpShBAiVgJEAAWHgDpQ1BQiVz5Pfkw6U+gQOlKgAye/Q4A6UkQAgl+HzDpT5APnPCJUfkg+SD7YPkhEkL5M/k0+Tj5Ofk++T/5OAkcAAgv0dwECRxgAgkVoBMJFbAS9fP08vczBwgJFcAZCRXQEoFzkHcfDgkVoB8JFbAeZe/k9AgzCTWwEgk1oBAsCAkcYA/5HvkZ+Rj5FPkT+RL5EPkA++D5AfkBiV4JGuAfCRrwHgXP9PgZGRkSCBMYGCG5MLj3OQcIkrEfAOlL0ACJUfkg+SD7YPkhEkL5M/k4+Tn5Pvk/+TIJGeATCRnwGAkaABkJGhASgXOQcx9ICRwQCPfYCTwQAUwOCRoAHwkaEB4lr+TyCBgJGgAZCRoQEBlo9zkHCQk6EBgJOgASCTxgD/ke+Rn5GPkT+RL5EPkA++D5AfkBiV3AEclu2R/JEdl+Bc/08hkTGRgIGRgSgbOQsvczBwyQEIldwBHJbtkfyRHZfgXP9PIIExgeBU8EDfAa5bv0+NkZyREZcoFzkHGfQv7z/vB8CNkZyR6A/5H4CBKC8w4MkBCJXcARyW7ZH8kR2X4Fz/TyCBMYHgVPBA3wGuW79PjZGckRGXKBc5Bxn0L+8/7xDAjZGckRGX6A/5HyCBjZGckRGXAZaPc5BwEZack46TMODJAQiV3AGRloyRkZeIIznwVJbtkfyRVZeAgYb/+c+RlhySCJXPk9+T7AHuhf+F4Fz/TyCBMYHgVPBAL18/Ty9zMHDfAa5bv0+NkZyREZcoFzkH0fPgXP9PgIGRgeBU8EDoD/kfYIPuhf+F4Fz/TzGDIIPuif+JIIGB4JDgD4wCwIgPmR8KlOL3KCsgg4HgiaPsif2JgIGAZICDgeCQ4N+Rz5EIlRCSpQEQkqQBiO6T4KDgsOCAk6YBkJOnAaCTqAGwk6kBh+CR4JCTowGAk6IBiuGR4JCTrwGAk64BjuWR4JCTsQGAk7ABheyQ4JCTswGAk7IBhOyQ4JCTtQGAk7QBgOyQ4JCTtwGAk7YBgeyQ4JCTuQGAk7gBguyQ4JCTuwGAk7oBhuyQ4JCTvQGAk7wBhOCAk74Bg+CAk78Bh+CAk8ABheCAk8EBgeCAk8IBCJWH4ZHgkJPFAYCTxAEQksYBEJLHARCSyAEQkskBCJWPkp+Sr5K/ks+S35Lvkv+SD5Mfk8+T35NMAWsBfAGqJLskwODQ4MYB9wFigUrgUOAOlFkDjAHGAW7iDpTCAggPGR+gDrEeIZYIlOEc8RzDMNEFSffGAfQBZYFK4FDgDpRZA5UBKA85H8kB35HPkR+RD5H/kO+Q35DPkL+Qr5CfkI+QCJXPkt+S75L/kg+TH5PPk9+TfAFrAYoBwODQ4A/A1gFtkW0B1wHtkfyRAZDwgeAtxwEJlcgP2R8BUBBAARURBXH3zgHfkc+RH5EPkf+Q75DfkM+QCJXcAe2R/JEBkPCB4C0JlQiVz5Pfk+wBYRVxBRn0IOAw4A/A2wENkAAg6fcRl6YbtwvogfmBAoDzgeAtrQEJlZwByQHfkc+RCJVPkl+Sf5KPkp+Sr5K/ks+S35Lvkv+SD5Mfk9+Tz5PNt963oZcPtviU3r8Pvs2/LAF0LssBIjAI9CrgGaIx4sMu0SzMDt0egi6ZJKokuyRnLXUvpQGUAQ6U5wV5AYoByAG3AaUBlAEOlMgFRy1GGwiUwQjRCEowFPRAXQHASVz2AUCD4RTxBAEFEQUh8H4sXy3IAd3PwgG2AQ6UygKhlg+2+JTevw++zb/Pkd+RH5EPkf+Q75DfkM+Qv5CvkJ+Qj5B/kF+QT5AIldwBIRUxBUH07ZH8kQGQ8IHgLWQvCZUIlQ6U5gIIle+S/5IPkx+TmgHmLv8kAOAQ4LgBpwEOlEoDH5EPkf+Q75AIlYEwQfCBMBjwgjDR9AnAEJJuAAiVgJFvAI1/gJNvAAiVgJFwAI1/gJNwAIHggJOwAICRsQCIf4RggJOxABCSswAIlR+TGC+AkQIBgRcR8J/vBsDo5vDglJGP74CTAgGJLw6UawOBL2DgDpR0BR+RCJUfkg+SD7YPkhEkL5M/k0+TX5Nvk3+Tj5Ofk6+Tv5Pvk/+TgJHKAZCRywGgkcwBsJHNAQCXoQWxBVHx4JHOAfCRzwGAgZCR0AGJJ4CDgJHKAZCRywGgkcwBsJHNARgWGQYaBhsGxPSAkcoBkJHLAaCRzAGwkc0BAZehCbEJgJPKAZCTywGgk8wBsJPNAQTAgJECAQ6UjAP/ke+Rv5GvkZ+Rj5F/kW+RX5FPkT+RL5EPkA++D5AfkBiVH5IPkg+2D5IRJC+TP5NPk1+Tb5N/k4+Tn5Ovk7+T75P/k4CR0QGQkdIBiSsp8OCR0QHwkdIBCZX/ke+Rv5GvkZ+Rj5F/kW+RX5FPkT+RL5EPkA++D5AfkBiVH5IPkg+2D5IRJC+TP5NPk1+Tb5N/k4+Tn5Ovk7+T75P/k4CR0wGQkdQBiSsp8OCR0wHwkdQBCZX/ke+Rv5GvkZ+Rj5F/kW+RX5FPkT+RL5EPkA++D5AfkBiVH5IPkg+2D5IRJC+TP5OPk5+Tr5O/k4CR2QGQkdoBoJHbAbCR3AEwkd0BAZahHbEdIy8tXy03IPAtVwGWoR2xHSCT3QGAk9kBkJPaAaCT2wGwk9wBgJHVAZCR1gGgkdcBsJHYAQGWoR2xHYCT1QGQk9YBoJPXAbCT2AG/ka+Rn5GPkT+RL5EPkA++D5AfkBiVmwGsAX+3+JSAkdUBkJHWAaCR1wGwkdgBZrWomwXAbz8Z8AGWoR2xHX+/ui+pL5gviCeGD5EdoR2xHWLgiA+ZH6ofux9qldH3vAEtwP+3+JSAkdUBkJHWAaCR1wGwkdgB5rWomwXA7z8Z8AGWoR2xHf+/ui+pL5gviCeOD5EdoR2xHeLgiA+ZH6ofux/qldH3hhuXC4hek0DI8iFQMEBAQFBAaFF8TyEVMQVBBVEFcfYIlXiUhLWCYIS9hLWBYIS9hbWCYIW9hbWBYIW97ubw4ICBgWCAg+Ho8OAQgoCBgmCAg4CBgWCAg+Do8OCAgYFggIPh6/DggIGEYICD4Ovw4ICBgWCAg+rn8OCAgYRggIOAgYJggIOAgYFggIOAgYBogIMQksEACJXPk9+TSC9Q4MoBhVafT/wBNJFJV19P+gGEkYgjafGQ4IgPmR/8AedZ/0+lkbSR/AHtWP9PxZHUkWYjUfQvt/iUjJGTL5CViSOMk4iBiSMLwGIwYfQvt/iUjJGTL5CViSOMk4iBgyuIgy+/BsCft/iUjJGDK4yTn7/fkc+RCJVIL1DgygGBVZ9P/AEkkcoBhVafT/wBlJFJV19P+gE0kTMjCfRAwCIjUfEjMHHwJDAo9CEwofAiMBH1FMAmMLHwJzDB8CQw2fQEwICRgACPdwPAgJGAAI99gJOAABDAhLWPdwLAhLWPfYS9CcCAkbAAj3cDwICRsACPfYCTsADjL/Dg7g//H+1Y/0+lkbSRL7f4lGYjIfSMkZCViSMCwIyRiSuMky+/CJVin9ABc5/wAYKf4A3xHWSf4A3xHZKf8A2Dn/ANdJ/wDWWf8A2ZJ3KfsA3hHfkfY5+wDeEd+R+9Ac8BESQIlaHiGi6qG7sb/QENwKofux/uH/8fohezB+QH9Qcg8KIbswvkC/ULZh93H4gfmR8alGn3YJVwlYCVkJWbAawBvQHPAQiV7g//HwWQ9JHgLQmU+JT/zw0A/wAAAACxAZgCRwF4AVgBoQEAAAAAVgIA'); - } - - public function testBlinkUnoSyntaxCheckError() - { - $files = array(array("filename" => "Blink.ino", "content" => "/*\n Blink\n Turns on an LED on for one second, then off for one second, repeatedly.\n \n This example code is in the public domain.\n *///\n \n// Pin 13 has an LED connected on most Arduino boards.\n// give it a name:\nint led = 13\n\n// the setup routine runs once when you press reset:\nvoid setup() { \n // initialize the digital pin as an output.\n pinMode(led, OUTPUT);\n pinMode(led); \n}\n\n// the loop routine runs over and over again forever:\nvoid loop() {\n digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)\n delay(1000); // wait for a second\n digitalWrite(led, LOW); // turn the LED off by making the voltage LOW\n delay(1000); // wait for a second\n}\n")); - $format = "syntax"; - $version = "105"; - $libraries = array(); - $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); - - $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); - - $client = static::createClient(); - - $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); - - $client->request('POST', '/'.$authorizationKey.'/v1', array(), array(), array(), $data); - - $response = json_decode($client->getResponse()->getContent(), true); - - $this->assertEquals($response["success"], false); - $this->assertEquals($response["success"], false); - $this->assertEquals($response["step"], 4); - $this->assertContains("Blink.ino:10:13:", $response["message"]); - $this->assertContains("expected ';' after top level declarator", $response["message"]); - $this->assertContains("no matching function for call to 'pinMode'", $response["message"]); - $this->assertContains("candidate function not viable: requires 2 arguments, but 1 was provided", $response["message"]); - // $this->assertContains("2 errors generated.", $response["message"]); //unfortunately we no longer show how many errors were generated - } - - public function testBlinkUnoCompileError() - { - $files = array(array("filename" => "Blink.ino", "content" => "/*\n Blink\n Turns on an LED on for one second, then off for one second, repeatedly.\n \n This example code is in the public domain.\n *///\n \n// Pin 13 has an LED connected on most Arduino boards.\n// give it a name:\nint led = 13\n\n// the setup routine runs once when you press reset:\nvoid setup() { \n // initialize the digital pin as an output.\n pinMode(led, OUTPUT);\n pinMode(led); \n}\n\n// the loop routine runs over and over again forever:\nvoid loop() {\n digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)\n delay(1000); // wait for a second\n digitalWrite(led, LOW); // turn the LED off by making the voltage LOW\n delay(1000); // wait for a second\n}\n")); - $format = "binary"; - $version = "105"; - $libraries = array(); - $build = array("mcu" => "atmega328p", "f_cpu" => "16000000", "core" => "arduino", "variant" => "standard"); - - $data = json_encode(array("files" => $files, "format" => $format, "version" => $version, "libraries" => $libraries, "build" => $build)); - - $client = static::createClient(); - - $authorizationKey = $client->getContainer()->getParameter("authorizationKey"); - - $client->request('POST', '/'.$authorizationKey.'/v1', array(), array(), array(), $data); - - $response = json_decode($client->getResponse()->getContent(), true); - - $this->assertEquals($response["success"], false); - $this->assertEquals($response["step"], 4); - $this->assertContains("Blink.ino:10:13:", $response["message"]); - $this->assertContains("expected ';' after top level declarator", $response["message"]); - $this->assertContains("no matching function for call to 'pinMode'", $response["message"]); - $this->assertContains("candidate function not viable: requires 2 arguments, but 1 was provided", $response["message"]); - // $this->assertContains("2 errors generated.", $response["message"]); //unfortunately we no longer show how many errors were generated - } - - public function testIncorrectInputs() - { - $this->markTestIncomplete("No tests for invalid inputs yet"); - } -} diff --git a/Symfony/web/favicon.ico b/Symfony/web/favicon.ico index 8648036..41b8b6e 100644 Binary files a/Symfony/web/favicon.ico and b/Symfony/web/favicon.ico differ diff --git a/apache-config b/apache-config index 34e6c45..a07cafb 100644 --- a/apache-config +++ b/apache-config @@ -1,7 +1,10 @@ -AliasMatch ^/compiler/?(.*) /opt/codebender/compiler/Symfony/web/$1 - - Options -Indexes FollowSymLinks MultiViews + + DocumentRoot /opt/codebender/compiler/Symfony/web + DirectoryIndex index.php + SetEnv APPLICATION_ENV "production" + + Options -Indexes +FollowSymLinks +MultiViews + Require all granted AllowOverride All - Order allow,deny - Allow from all - + + \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh index da601df..f4ee123 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -14,7 +14,7 @@ if [[ "$OSTYPE" == "linux-gnu" ]]; then sudo apt-get install -y php5-intl fi # Install dependencies - sudo apt-get install -y apache2 libapache2-mod-php5 php-pear php5-curl php5-sqlite acl curl git + sudo apt-get install -y apache2 libapache2-mod-php5 php-pear php5-xdebug php5-curl php5-sqlite acl curl git # Enable Apache configs sudo a2enmod rewrite sudo a2enmod alias @@ -57,22 +57,9 @@ if [[ "$OSTYPE" == "linux-gnu" ]]; then if [[ ! $TRAVIS ]]; then - sudo dd if=/dev/zero of=cache-fs bs=1024 count=0 seek=200000 - sudo dd if=/dev/zero of=logs-fs bs=1024 count=0 seek=200000 - - yes | sudo mkfs.ext4 cache-fs - yes | sudo mkfs.ext4 logs-fs - mkdir -p `pwd`/Symfony/app/cache/ mkdir -p `pwd`/Symfony/app/logs/ - echo "`pwd`/cache-fs `pwd`/Symfony/app/cache/ ext4 loop,acl 0 0" | sudo tee -a /etc/fstab > /dev/null 2>&1 - echo "`pwd`/logs-fs `pwd`/Symfony/app/logs/ ext4 loop,acl 0 0" | sudo tee -a /etc/fstab > /dev/null 2>&1 - cat /etc/fstab - - sudo mount `pwd`/Symfony/app/cache/ - sudo mount `pwd`/Symfony/app/logs/ - sudo rm -rf `pwd`/Symfony/app/cache/* sudo rm -rf `pwd`/Symfony/app/logs/* @@ -102,6 +89,6 @@ cp app/config/parameters.yml.dist app/config/parameters.yml if [[ "$OSTYPE" == "linux-gnu" ]]; then sudo cp /opt/codebender/$PACKAGENAME/apache-config /etc/apache2/sites-available/codebender-compiler cd /etc/apache2/sites-enabled - sudo ln -s ../sites-available/codebender-compiler 00-codebender-compiler + sudo ln -s ../sites-available/codebender-compiler 00-codebender-compiler.conf sudo service apache2 restart fi diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 4486d0e..db15079 100755 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -2,10 +2,10 @@ sudo apt-get install -y unzip cd ~ wget https://github.com/codebendercc/arduino-core-files/archive/master.zip -unzip master.zip +unzip -q master.zip sudo cp -r arduino-core-files-master /opt/codebender/codebender-arduino-core-files rm master.zip wget https://github.com/codebendercc/external_cores/archive/master.zip -unzip master.zip +unzip -q master.zip sudo cp -r external_cores-master /opt/codebender/external-core-files cd - \ No newline at end of file