NPU Repository

Skip to content
Snippets Groups Projects
  1. Dec 14, 2017
    • Justin M. Wray's avatar
      Upgrade from Ubuntu 14.04 (Trusty) to Ubuntu 16.04 (Xenial) (#601) · 4dbbf104
      Justin M. Wray authored
      ### Upgrade from Ubuntu 14.04 (Trusty) to Ubuntu 16.04 (Xenial)
      
      * **NOTE**: These changes require `Xenial` to be used from this point forward. `Trusty` will no longer work as there are _various incompatibilities_.
      
      * The platform is now exclusively supported on Ubuntu 16.04 (Xenial).  Trusty (14.04) is no longer supported after this commit.
      
      * HHVM has been upgraded to to version 3.21.
      
      * Provision, Docker, and Vagrant configurations have been updated to support 16.04. This includes Travis builds which utilizes the Docker image (PR #569).
      
      * Provision Changes:
      
        * HHVM repo and repo keys updated for Xenial
      
        * HHVM "restarted" instead of "started" after HHVM repo mode enabled. Enabling repo mode appears to start HHVM before permissions are applied to repo file. Therefore it must be restarted.
      
        * `osquery` repo source updated for Xenial
      
        * `node.js` legacy purge removed before installation, as this is not required for Xenial
      
        * Package `language-pack-en` removed, this is installed and no longer required.
      
        * Package `php5-cli` replaced with `php7.0-cli` for compatibility with Xenial.
      
        * MySQL configuration file changed from `/etc/mysql/my.cnf` to `/etc/mysql/mysql.conf.d/mysqld.cnf` for compatibility with Xenial.
      
      * Vagrant Changes:
      
        * Base VM changed to Xenial
      
      * Docker Changes:
      
        * Images for standalone and multi-setup changed to Xenial
      
        * Web directory permissions set to `www-data`. Otherwise, the web directory will be owned by root and cause permissions issues.
      
        * MySQL permissions enforced on `/var/lib/mysql and /var/run/mysql`. Otherwise, these directories will be owned by root and MySQL will not function.
      
        * HHVM explicitly started as `www-data`. Docker does not allow HHVM startup (running under root) to spawn an HHVM process under another user (www-data).
      
        * `sudo` and `apt-utils` installed. These are required packages for provision.
      
        * Based on recommended HHVM DockerFile, `ENV HHVM_DISABLE_NUMA` parameter added and set to true.
  2. Nov 18, 2017
    • Justin M. Wray's avatar
      Major Performance Enhancements and Bug Fixes (#594) · d2659ff6
      Justin M. Wray authored
      * Major Performance Enhancements and Bug Fixes
      
      * **NOTICE**:  _This PR is extremely large.  Due to the interdependencies, these code changes are being included as a single PR._
      
      * **Local Caching of Database and Memcached Results**
      
        * Replaced PR #574
      
        * Results from the database (MySQL) are stored and queried from the Cache service (Memcached). Results from Memcached are now stored locally within HHVM memory as well.
      
        * New class `Cache` has been added, with four methods:
      
          * `setCache()`
          * `getCache()`
          * `deleteCache()`
          * `flushCache()`
      
        * The new `Cache` class object is included as a static property of the `Model` class and all children.
      
        * Through the new `Cache` object, all `Model` sub-classes will automatically utilize the temporary HHVM-memory cache for results that have already been retrieved.
      
        * The `Cache` object is created and used throughout a single HHVM execution thread (user request).
      
        * This change results in a massive reduction in Memcached requests (over 99% - at scale), providing a significant improvement in scalability and performance.
      
        * The local cache can be deleted or flushed from the `Model` class or any child class with the usage of `deleteLocalCache()`.  The `deleteLocalCache()` method works like `invalidateMCRecords()`.  When called from a child class, a `$key` can be passed in, matching the MC key identifier used elsewhere, or if no `$key` is specified all of the local caches for that class will be deleted.  If the calling class is `Model` then the entire local cache is flushed.
      
        * Some non-HTTP code has local cache values explicitly deleted, or the local cache completely flushed, as the execution thread is continuous:
      
          * Prevent `autorun.php` from storing timestamps in the local cache, forever (the script runs continuously).
      
          * Flush the local cache before the next cycle of `bases.php` to ensure the game is still running and the configuration of the bases has not changed (the script runs continuously).
      
          * Flush the local cache before the next import cycle of `liveimport.php` to ensure we get the up-to-date team and level data (the script runs continuously).
      
        * The `Cache` class is specifically separate from `Model` (as an independent class) so that other code may instantiate and utilize a temporary (request-exclusive) local-memory-based caching solution, with a common interface.  The usage provides local caching without storing the data in MySQL, Memcached, or exposing it to other areas of the application. (For example, this is being utilized in some `Integration` code already.)
      
        * Implemented CR from PR #574.
      
        * Relevant:  Issue #456 and Comment https://github.com/facebook/fbctf/issues/456#issuecomment-332952554
      
      * **Blocking AJAX Requests**
      
        * Replaced PR #575
      
        * Expansion and Bug Fixes of PR #565
      
        * AJAX requests for the gameboard are now individually blocking.  A new request will not be dispatched until the previous request has completed.
      
        * AJAX requests will individually stop subsequent requests on a hard-error.
      
        * The blocking of continuous AJAX requests, when the previous has not yet returned, or on a hard error, provides a modest performance benefit by not compounding the issue with more unfulfillable requests.
      
        * Forceful refreshes are still dispatched every 60 seconds, regardless of the blocking state on those requests.
      
        * Relevant:  Issue #456 and Comment https://github.com/facebook/fbctf/issues/456#issuecomment-332952554
      
      * **AJAX Endpoint Optimization**
      
        * Removed nested loops within multiple AJAX endpoints:
      
          * `map-data.php`
      
          * `country-data.php`
      
          * ` leaderboard.php`
      
        * All Attachments, including Link and Filename, are now cached and obtained through:  `Attachment::genAllAttachmentsFileNamesLinks()`.
      
        * All Team names of those who have completed a level, are now cached and obtained through `MultiTeam::genCompletedLevelTeamNames()`.
      
        * All Levels and Country for map displays are cached and obtained through `Level::genAllLevelsCountryMap()` and `Country::genAllEnabledCountriesForMap()`.
      
        * Relevant:  Issue #456
      
      * **Memcached Cluster Support**
      
        * The platform now supports a cluster of Memcached nodes.
      
        * Configuration for the `MC_HOST` within the `settings.ini` file is now an array, instead of a single value:
      
          * `MC_HOST[] = 127.0.0.1`
      
        * Multiple Memcached servers can be configured by providing additional `MC_HOST` lines:
      
          * `MC_HOST[] = 1.2.3.4`
      
          * `MC_HOST[] = 5.6.7.8`
      
        * The platform uses a Write-Many Read-Once approach to the Memcached Cluster.  Specifically, data is written to all of the configured Memcached nodes and then read from a single node at random.  This approach ensures that all of the nodes stay in sync and up-to-date while providing a vital performance benefit to the more expensive and frequent operation of reading.
      
        * The existing `Model` methods (`setMCRecords()` and `invalidateMCRecords()`) all call and utilize the new cluster methods:
      
          * `writeMCCluster()`
      
          * `invalidateMCCluster()`
      
        * The flushing of Memcached has also been updated to support the multi-cluster approach:  `flushMCCluster()`.
      
        * Note that the usage of a Memcached Cluster is seamless for administrators and users, and works in conjunction with the Local Cache.  Also note, the platform works identically, for administrators and users, for both single-node and multi-node Memcached configurations.
      
        * The default configuration remains a single-node configuration.  The utilization of a Memcached Cluster requires the following:
      
          * The configuration and deployment of multiple Memcached nodes (the `quick_setup install_multi_cache` or Memcached specific provision, will work).
      
          * The modification of `settings.ini` to include all of the desired Memcached hosts.
      
          * All Memcached hosts must be identically configured.
      
        * Usage of a Memcached Cluster is only recommended in the Multi-Server deployment modes.
      
        * Relevant:  Issue #456
      
      * **Load Balancing of Application Servers (HHVM)**
      
        * The platform now supports the ability to load balance multiple HHVM servers.
      
        * To facilitate the load balancing of the HHVM servers, the following changes were made:
      
          * Scripts (`autorun`, `progressive`, etc.) are now tracked on a per-server level, preventing multiple copies of the scripts from being executed on the HHVM servers.
      
          * Additional database verification on scoring events to prevent multiple captures.
      
        * Load Balancing of HHVM is only recommended in the Multi-Server deployment modes.
      
        * Relevant:  Issue #456
      
      * **Leaderboard Limits**
      
        * `MultiTeam::genLeaderboard()` now limits the total number of teams returned based on a configurable setting.
      
        * A new argument has been added to `MultiTeam::genLeaderboard()`: `limit`.  This value, either `true` or `false`, indicates where the limit should be enforced, and defaults to `true`.
      
        * When the data is not cached, `MultiTeam::genLeaderboard()` will only build, cache, and return the number of teams needed to meet the limit.
      
        * When the data is already cached, `MultiTeam::genLeaderboard()` will ensure the limit value has not changed and returned the cached results.  If the configured limit value has been changed, `MultiTeam::genLeaderboard()` will build, cache, and return the number based on the new limit.
      
        * The "Scoreboard" modal (found from the main gameboard) is a special case where all teams should be displayed.  As such, the Scoreboard modal sets the `limit` value to `false` retuning all teams.  This full leaderboard will be cached, but all other display limits are still enforced based on the configured limit.  Once invalidated, the cached data will return to the limited subset.
      
        *  Because a full leaderboard is not always cached, this does result in the first hit to the Scoreboard modal requiring a database hit.
      
        * A user, whose rank is above the limit, will have their rank shown to them as `$limit+`.  For example, if the limit is set to `50` and the user's rank is above `50`, they would see:  `51+` as their rank.
      
        * Overall, the caching of the Leaderboard, one of the more resource-intensive and frequent queries, resulted in significant performance gains.
      
        * The Leaderboard limit is configurable by administrators within the administrative interface.  The default value is `50`.
      
        * Relevant:  Issue #456
      
      * **Activity Log Limits**
      
        * The Activity Log is now limited to the most recent `100` log entries.  The value is not configurable.
      
        * The activity log is continually queried and contains a large amount of data, as such, it is a very resource-intensive request.
      
        *  The limit on the results built, cached, and returned for the activity log provides a notable improvement in performance.
      
        * Relevant:  Issue #456
      
      * **Database Optimization**
      
        * Expansion of PR #564
      
        * Added additional indexing of the database tables in the schema.
      
        * The additional indexing provides further performance improvements to the platform queries, especially those found in `MultiTeam` and those queries continually utilized as a result of the AJAX calls.
      
        * Relevant:  Issue #456 and Comment https://github.com/facebook/fbctf/issues/456#issuecomment-332952554
      
      * **Team and MultiTeam Performance Improvements**
      
        * Updated numerous `Team::genTeam()` calls to used the cached version: `MultiTeam::genTeam()`.
      
        * Optimized the database query within `MultiTeam::genFirstCapture()` to return the `team_id` and build the `Team` from the cache.
      
        * Optimized the database query within `MultiTeam::genCompletedLevel()` to return the `team_id` and build the `Team` from the cache.
      
        * Optimized the database query within `MultiTeam::genAllCompletedLevels()` to return the `team_id` and build the `Team` from the cache.
      
        * A full invalidation of the `MultiTeam` cache is no longer executed when a new team is created.  Newly created teams will not have any valid scoring activity.  Delaying the rebuild of the scoring related cache provides a modest performance improvement.  The new team will not show up in certain areas (namely the full scoreboard) until they or someone else perform a scoring action.  To ensure the team is properly functioning, following cache is specifically invalided on a new team creation:
      
          * `ALL_TEAMS`
          * `ALL_ACTIVE_TEAMS`
          * `ALL_VISIBLE_TEAMS`
          * `TEAMS_BY_LOGO`
      
        * Fixed an extremely rare race condition within `MultiTeam::genFirstCapture()`.
      
        * Relevant:  Issue #456
      
      * **Combined Awaitables**
      
        * Combined Awaitables which were not in nested loops.
      
        * Combined Awaitables found in some nested loops, where existing code provided a streamlined approach.
      
        * Given the lack of support for concurrent queries to a single database connection, some queries were combined via `multiQuery()` (in the case where the queries were modifying data within the database).  TODO:  Build and utilize additional `AsyncMysqlConnection` within the pool for suitable concurrent queries.
      
        * Annotated Awaitables within a nested loop for future optimization.
      
        * Relevant:  Issue #577
      
      * **Facebook and Google Login Integration**
      
        * Replaced PR #573
      
        * The platform now supports Login via OAuth2 for Facebook and Google. When configured and enabled, users will have the option to link and login to their existing account with a Facebook or Google account.
      
        * Automated registration through Facebook or Google OAuth2 is now supported. When configured and enabled, users will have the option to register an account by using and linking an existing account with Facebook or Google.
      
        * New `configuration` options added to the database schema:
      
          * Added `facebook_login`. This configuration option is a toggleable setting to enable or disable login via Facebook.
      
          * Added `google_login`. This configuration option is a toggleable setting to enable or disable login via Google.
      
          * Added `facebook_registration`. This configuration option is a toggleable setting to enable or disable registration via Facebook.
      
          * Added `google_registration`. This configuration option is a toggleable setting to enable or disable registration via Google.
      
          * Added `registration_prefix`. This configuration option is a string that sets the prefix for the randomly generated username/team name for teams registered via (Facebook or Google) OAuth.
      
        * New Integration section within the Administrative interface allows for control over the Facebook and Google Login, Registration, and the automatic team name prefix option.
      
        * Overhauled the Login page to support the new Login buttons.  Login page now displays appropriate messages based on the configuration of login.
      
        * Login form is dynamically generated, based on the configuration options and settings.
      
        * Overhauled the Registration page to support the new Registration buttons.  The registration page now displays appropriate messages based on the configuration of registration.
      
        * The registration form is dynamically generated, based on the configuration options and settings.
      
        * Account Linking for Facebook sets both the Login OAuth values and the LiveSync values (single step for both).
      
        * Account Linking for Google sets both the Login OAuth values and the LiveSync values (single step for both).
      
        * Facebook Account linkage option has been added to the Account modal.
      
        * The Account modal now shows which accounts are already linked.
      
        * The Account modal will color-code the buttons on an error (red) and success (green).
      
        * New table "teams_oauth" has been added to handle the OAuth data for Facebook and Google account linkage.
      
        * New class `Integration` handles the linkage of Facebook or Google accounts with an FBCTF account (both Login OAuth values and the LiveSync values). The Integration class also includes the underlying methods for authentication in both the linkage and login routines and the OAuth registration process.
      
        * New URL endpoints have been created and simplified for the `Integration` actions:
      
          * New data endpoint `data/integration_login.php`. This endpoint accepts a type argument, currently supporting types of `facebook` and `google`. Through this endpoint, the login process is handled in conjunction with the Integration class.
      
          * The new callback URL for Facebook Login: `/data/integration_login.php?type=facebook`
      
          * The new callback URL for Google Login: `/data/integration_login.php?type=google`
      
          * New data endpoint data/integration_oauth.php. This endpoint accepts a type argument, currently supporting types of `facebook'`and `google`. Through this endpoint, the OAuth account linkage is handled in conjunction with the Integration class.
      
          * The new callback URL for Facebook linkage: /data/integration_login.php?type=facebook
      
          * The new callback URL for Google linkage: /data/integration_login.php?type=google
      
          * Old Google-specific endpoint (data/google_oauth.php) has been removed.
      
        * New Team class methods: `genAuthTokenExists()`, `genTeamFromOAuthToken()`, `genSetOAuthToken()`.
      
          * `Team::genAuthTokenExists()` allows an OAuth token to be verified.
      
          * `Team::genTeamFromOAuthToken()` returns a Team object based on the OAuth token supplied.
      
          * `Team::genSetOAuthToken()` sets the OAuth token for a team.
      
        * The `settings.ini` (including the packaged example file) and `Configuration` have methods to verify and return Facebook and Google API settings.
      
          * `Configuration::getFacebookOAuthSettingsExists()` verifies the Facebook API _App ID_ and _APP Secret_ are set in the `settings.ini` file.
      
          * `Configuration::getFacebookOAuthSettingsAppId()` returns the Facebook API _App ID_.
      
          * `Configuration::getFacebookOAuthSettingsAppSecret()` returns the Facebook API _App Secret_.
      
          * `Configuration::getGoogleOAuthFileExists()` verifies the Google API JSON file is set and exists in the `settings.ini` file.
      
          * `Configuration::getGoogleOAuthFile()` returns the filename for the Google API JSON file.
      
          * All of Facebook and Google API configuration values are cached (in Memcached) to prevent the repeated loading, reading, and parsing of the `settings.ini` file.
      
        * To use the new Facebook or Google integration the following must be completed:
      
          * A Facebook and/or Google Application must be created, and OAuth2 API keys must be obtained.
      
          * The API keys must be provided in the Settings.ini file.
      
          * Desired settings must be configured from within the administrative interface (Configuration) - the default has all integration turned off.
      
        * The Facebook OAuth code provides CSRF protection through the Graph SDK.
      
        * The Google OAuth code provides CSRF protection through the usage of the `integration_csrf_token` cookie and API state value.
      
        * Note: Facebook Login/Integration will not work in development mode - this is due to a pending issue in the Facebook Graph SDK (facebook/php-graph-sdk#853) utilization of the pending PR (facebook/php-graph-sdk#854) resolves this issue. Alternatively, the Integration with Facebook will work in production mode, the recommended mode for a live game.
      
        * Implemented CR from PR #573.
      
        * Relevant:  PR #591 and PR #459.
      
      * **LiveSync API and LiveImport Script Update**
      
        * LiveSync has been updated to support and supply Facebook and Google OAuth output. All of the users LiveSync integrations (FBCTF, Facebook, and Google) are now provided through the API. As a result, so long as one of the three LiveSync methods are configured by the user (which happens automatically when linking an account to Facebook or Google) the data will become available through the LiveSync API.
      
        * LiveSync now includes a "general" type. The new `general` type output includes the scoring information using the local team name on the FBCTF instance. This new type is not for importation on another FBCTF instance but does provide the opportunity for third-parties to use the data for score tracking, metric collections, and displays. As such, this new LiveSync data allows the scoring data for a single FBCTF instance to be tracked.
      
        * The `liveimport.sh` script, used to import LiveSync API data, will ignore the new `general` LiveSync type.
      
        * Updated `Team::genLiveSyncKeyExists()` and `Team::genTeamFromLiveSyncKey()` to use the new Integration class methods:  `Integration::genFacebookThirdPartyExists)` and `Integration::genFacebookThirdPartyEmail()`.
      
        * Within the `liveimport.sh` script: when the type is `facebook_oauth`, `Team::genLiveSyncKeyExists()` and `Team::genTeamFromLiveSyncKey()` properly use the Facebook `third_party_id`.
      
        * `Integration::genFacebookThirdPartyExists()` and `Integration::genFacebookThirdPartyEmail()` query the Facebook API for the coorosponding user, storing the results in a temporary HHVM-memory cache, via  the `Cache` class.
      
        * Given that `liveimport.sh` now needs to query the Facebook API for any `facebook_oauth` typed items, the script will utilize the HHVM-memory cache of `Integration` to limit the number of hits to the Facebook API.
      
        * The `liveimport.sh` script now includes the `Cache` class and the Facebook Graph SDK.
      
        * Relevant:  PR #459.
      
      * **Error and Exception Handling**
      
        * All Exceptions, including Redirect Exceptions, are now caught.
      
        * The NGINX configuration has been updated to catch errors from HHVM (FastCGI) and return `error.php`.
      
        * The `error.php` page has been updated with a themed error page.
      
        * The `error.php` page will redirect to `index.php?page=error` so long as `index.php?page=error` is not generating any HTTP errors.  If an error is detected on `index.php?page=error` then no redirect will occur.  The verification of the HTTP status ensures no redirect loops occur.
      
        * The `DataController` class now includes a `sendData()` method to catch errors and exceptions.  `DataController` children classes now utilize `sendData()` instead of outputing their results directly.
      
        * On Exception within an AJAX request, an empty JSON array is returned.  This empty array prevents client-side errors.
      
        * The `ModuleController` class now includes a `sendRender()` method to catch errors and exceptions.  `ModuleController` children classes now utilize `sendRender()` instead of outputing their results directly.
      
        * On Exception within a Module request, an empty string is returned.  This empty string prevents client-side and front-end errors.
      
        * A new AJAX endpoint has been added:  `/data/session.php`.  The response of the endpoint is used to determine if the user's session is still active.  If a user's session is no longer active, they will be redirected from the gameboard to the login page.  This redirection ensures that they do not continually perform AJAX requests.
      
        * Custom HTTP headers are used to monitor AJAX responses:
      
          * The Login page now includes a custom HTTP header: `Login-Page`.
      
          * The Error page now includes a custom HTTP header:  `Error-Page`.
      
        * The custom HTTP headers are used client-side (JS) to determine if a request or page rendered an error or requires authentication.
      
        * Exception log outputs now include additional information on which Exception was thrown.
      
        * Users should no longer directly receive an HTTP 500.
      
        * These Exception changes prevent the error logs from being filled with unauthenticated requests.  The changes also provide a user-friendly experience when things malfunction or a user needs to reauthenticate.
      
        *   Relevant:  #563
      
      * **Team Account Modal Update**
      
        * Users can now change their team name from within the Account modal.
      
        * The account Modal now contains the following options:
      
          * Team Name
      
          * Facebook Account Linkage
      
          * Google Account Linkage
      
          * FBCTF LiveSync Authentication
      
        * Relevant:  PR #459.
      
      * **Non-Visible/Inactive Team Update**
      
        * Ensure that non-visible or inactive team do not show up for any other users.
      
        * Non-Visible/Inactive teams are not awarded as the "first capture."
      
        * Non-Visible/Inactive teams do not show in the "captured by" list.
      
        * Countries will not show as captured (for other teams) if only captured by a Non-Visible/Inactive team.
      
        * Activity Log entries for a Non-Visible or Inactive team are not included in the activity log for other users.
      
        * Updated `ScoreLog::genAllPreviousScore()` and `ScoreLog::genPreviousScore()` to only include Visible and Active teams, or the user's own team.
      
        * Teams who are Non-Visible or Inactive will have a rank of "N/A."
      
        * Relevant:  PR #513
      
      * **Mobile Page Update**
      
        * The mobile page is shown when a user's window has a resolution under `960px`.  While this is geared towards mobile users, it can happen when the window size on a non-mobile device is too small.
      
        * The mobile page now includes a "Refresh" button, which will reload the page.
      
        * The mobile page will refresh, attempting to re-render correctly, after `2` seconds.
      
        * If a user resizes their window to a larger size, they should reload into a properly displayed screen, and not the mobile warning.
      
      * **Login and Registration JS Fixes**
      
        * Consistently corrected the usage of `teamname` and `team_name` across PHP and JS code.
      
        * Ensured that all JavaScript is using `team_name`.
      
        * Ensured that all PHP is using `team_name` when interacting with JS.
      
        * Updated the input filters within PHP when retrieving input for the team name, using `team_name`.
      
        * Updated Login errors to highlight the username and password fields.
      
        * Relevant:  Issue #571, Issue #558, Issue #521, PR #592, and PR #523
      
      * **System Statistics JSON Endpoint**
      
         * A new administrative-only JSON endpoint has been added that provides statistical data about the platform and game.
      
        * The endpoint is found at `/data/stata.php`.  Access to the endpoint requires an authenticated administrative session.
      
        * The endpoint provides the following information:
      
          * Number of Teams (`teams`)
      
          * Number of Sessions (`sessions`)
      
          * Total Number of Levels (`levels`)
      
          * Number of Active Levels (`active_levels`)
      
          * Number of Hints (`hints`)
      
          * Number of Captures (`captures`)
      
          * `AsyncMysqlConnectionPool` Statistics (`database`)
      
            * Created Connections (`created_pool_connections`)
      
            * Destroyed Connections (`destroyed_pool_connections`)
      
            * Connection Requests (`connections_requested`)
      
            * Pool Hits (`pool_hits`)
      
            * Pool Misses (`pool_misses`)
      
          * `Memcached` Statistics (`memcached`)
      
            * Node Address
      
              * Node Address:Port
      
                * Process ID (`pid`)
      
                * Uptime (`uptime`)
      
                * Threads (`threads`)
      
                * Timestamp (`time`)
      
                * Size of Pointer (`pointer_size`)
      
                * Total User Time for Memcached Process (`rusage_user_seconds`)
      
                * Total User Time for Memcached Process (`rusage_user_microseconds`)
      
                * Total System Time for Memcached Process (`rusage_system_seconds`)
      
                * Total System Time for Memcached Process (`rusage_system_microseconds`)
      
                * Current Items in Cache (`curr_items`)
      
                * Total Items in Cache (`total_items`)
      
                * Max Bytes Limit (`limit_maxbytes`)
      
                * Number of Current Connections (`curr_connections`)
      
                * Number of Total Connections (`total_connections`)
      
                * Number of Current Connection Structures Allocated (`connection_structures`)
      
                * Number of Bytes Used (`bytes`)
      
                * Total Number of Cache Get Requests (`cmd_get`)
      
                * Total Number of Cache Set Requests (`cmd_set`)
      
                * Total Number Successful of Cache Retrievals (`get_hits`)
      
                * Total Number Unsuccessful of Cache Retrievals (`get_ misses`)
      
                * Total Number of Cache Evictions (`evictions`)
      
                * Total Number of Bytes Read (`bytes_read`)
      
                * Total Number of Bytes Written (`bytes_writter`)
      
                * Memcached Version (`version`)
      
          * System Load Statistics (`load`)
      
            * One Minute Average (`0`)
      
            * Five Minute Average (`1`)
      
            * Fifteen Minute Average (`2`)
      
          * System CPU Utilization (`load`)
      
            * Userspace Utilization Percentage (`user`)
      
            * Nice Utilization Percentage (`nice`)
      
            * System Utilization Percentage (`sys`)
      
            * Idle Percentage (`idle`)
      
        * The endpoint provides current data and can be pooled/ingested for historical data reporting.
      
        * For more information on the `AsyncMysqlConnectionPool` statistics, please see:  https://docs.hhvm.com/hack/reference/class/AsyncMysqlConnection/ and https://docs.hhvm.com/hack/reference/class/AsyncMysqlConnectionPool/getPoolStats/
      
        * For more information on the `Memcached` statistics, please see:  https://github.com/memcached/memcached/blob/master/doc/protocol.txt and https://secure.php.net/manual/en/memcached.getstats.php
      
      * **Miscellaneous Changes**
      
        * Added `Announcement` and `ActivityLog` to `autorun.php`.
      
        * Added `Announcement` and `ActivityLog` to `bases.php`.
      
        * Added/Updated UTF-8 encoding on various user-controlled values, such as team name.
      
        * Changed the "Sign Up" link to a button on the login page.
      
        * Allow any Logo to be re-used once all logos are in use.
      
        * Invalidate Scores and Hint cache when a Team is deleted.
      
        * Reverify the game status (running or stopped) before the next cycle of base scoring in `bases.php`.
      
        * Allow the game to stop even if some scripts (`autorun`, `bases`, `progressive`, etc.) are not running.
      
        * Fixed a bug where teams with a custom logo could not be edited by an administrator.
      
        * Added "Reset Schedule" button to administrative interface to completely remove a previously set game schedule.  The game schedule can only be reset if the game is not running.  Otherwise, the existing schedule must be modified.
      
        * Moved "Begin Game," "Pause Game," and "End Game" outside of the scrollable admin list into a new fixed pane below the navigation list.
      
        * Formatted all code files as part of this PR.
      
        * Updated ActivityLog to delete entries when deleting a team.
      
        * Updated PHPUnit tests based on the new changes.
  3. Oct 27, 2017
    • Justin M. Wray's avatar
      Google OAuth Security Update (#591) · 7d782d30
      Justin M. Wray authored
      * Google OAuth Security Update
      
      * The Google OAuth process now sets a CSRF token.
      
      * Added Secure Only and HTTP Only to the Integration cookie.
      7d782d30
    • Justin M. Wray's avatar
      Attachment Security Update (#590) · 780071b7
      Justin M. Wray authored
      * Attachment Security Update
      
      * Attachments have been moved out of a web accessible direcotry (`/var/www/fbctf/src/data/`) and now reside in `/var/www/fbctf/attachments`.
      
      * Attachment downloads are now handled by an endpoint in `/data`: `attachment.php`.
      
      * All links to attachments now refer to the correct `attachment.php` endpoint location.
      
      * The `tar` command within the Attachment Import function now sets the mode to 600 at time of extraction.
      
      * The Attachment Import functionality will no longer change or attempt to change permissions on the current or parent directories.
      
      * The Attachment Import functionality will no longer change permissions on any directories, though subdirectories are not supported.
      
      * Attachment filenames will no longer be altered, excluding the inclusion of the file hash.
      
      * The provision script has been updated to support the new Attachment directory location.
      
      * Attachment specific directives are no longer set in the Mult-Server Nginx configuration.
      
      * Attachment location information has been updated in the `.gitignore` configuration.
      
      * Fixed an issue with the deletion path.
      780071b7
  4. Oct 23, 2017
  5. Sep 28, 2017
  6. Sep 20, 2017
    • Justin M. Wray's avatar
      Travis-CI to use Docker (#569) · b9822ff3
      Justin M. Wray authored
      * Travis-CI now builds a docker image and uses the docker image for build testing.
      
      * Split docker build, docker run, and the docker execution of `run_tests.sh` into separate steps.
      
      * Added a service status check to `run_tests.sh` to ensure services are running or wait until they are.  The service test process will not directly return any error status; instead, the process will wait (up to 10 times, 10 seconds each) for the services to come online before finally failing with an error or continuing if everything is ready.
      
      * This change removes our dependency on Travis-provided images and allows us to move away from Ubuntu 14.04 when ready.
      b9822ff3
  7. Sep 12, 2017
  8. Aug 31, 2017
    • Justin M. Wray's avatar
      Update CONTRIBUTING (#557) · ccc3ae76
      Justin M. Wray authored
      * Included message indicating that Pull Requests need to be submitted against `dev`.
      
      * Updated commands to branch from `dev`.
      ccc3ae76
    • Justin M. Wray's avatar
      Added Quick Setup Guide to README (#556) · 88827c23
      Justin M. Wray authored
      * Updated links and information related to the installation process.
      
      * Included a link to Quick Setup Guide.
      88827c23
    • Justin M. Wray's avatar
      Downgraded DropkickJS and Streamlined Provision for NodeJS/Downloads (Fixes: #554) (#555) · 93387b35
      Justin M. Wray authored
      * Downgraded Dropkick.js to version 2.1.10.  The project originally was built using 2.1.10 and specified a near version in the 2.x.x release family.  On August 27th 2017 Dropkick.js released version 2.2.0 which is incompatible with ES6 specs. The incompatibility with the new release of Dropkick.js caused the provisioning of the platform to fail.
      
      * Moved the installation process for Node.js to a function within `lib.sh`.  This change streamlines the provision script.
      
      * Removed the installation of `wget` from provisioning.  `wget` is no longer used within the project and is therefore unneeded.
      
      * Updated the `dl()` download function within the provision script to use `curl` exclusively, with retry options.  The retry options are set to 5 retries with a 15-second delay between retries.  The addition of the retry option ensures the provision can continue if there is a temporary issue with a remote connection or availability of a remote resource.
      
      * Added the `dl_pipe()` download function to the provision script.  This download function provided the data from the remote resource via standard output to be piped into another command.  As piping downloads within the provisioning process have become more common, this function streamlines the process.
      
      * Fixes #554
      
      * Updates fixes for #550
      93387b35
  9. Aug 28, 2017
  10. Aug 05, 2017
    • Justin M. Wray's avatar
      Merge /master into /dev (#543) · ed0a2257
      Justin M. Wray authored
      Merged `master` onto `dev`
      
      Commits:
      
      * add hindi translation (f9f69a7c)
      * added hindi translation (c5a3eb26)
      * Update lang_hi.php (6bf83172)
      * Merge pull request #454 from Akhil09/master (f19b5d54)
      * Error Checking During Build Tests (#452) (de72b287)
      * HHVM/Hack Typing Error Fixes (#450) (8e4151e5)
      * Require bxslider version 4.2.6 (Fixes #455) (#458) (c2957d7c)
      * Fixed Syntax Errors in Hindi Language (Fixes Build Errors) (#460) (899ab2be)
      * Automated Game Start and Stop (#449) (ca400912)
      * Attachments and Links Import/Export, Database Restore, and Control Cleanup (#451)(be35c6ba)
      * Update README.md (8d1db8c4)
      * Update README.md (8f161417)
      * Update README.md (53a6fa7b)
      * Update README.md (300091c7)
      * Live Sync API (#459) (0b7ca09a)
      * I think its bad (#446) (d3265647)
      * Updated LiveSync Security (#494) (e880251b)
      * Temp fix for issue 499 & 500. Forcing Grunt to continue as it is not correctly detecting node_modules in the folder (#502) (dd3c8742)
      * Merge Deconflict of /dev and /master (#503) (51e06a70)
      * Added Slack registration link to README (b11322e1)
      * Merge branch 'dev' into WraySec/fbctf/merge@7f8c281
      * Fixed conflict in ScoreLog (e181da25)
      * Fixed conflict in ScoreLog (dd9de6e5)
      * Fixed conflict in Control (f7c64396)
      * Merge /dev/ to /master (#542) (3047351e)
      ed0a2257
    • Justin M. Wray's avatar
      Merge /dev/ to /master (#542) · 3047351e
      Justin M. Wray authored
      Merge of `dev` into `master`
      
      Commits:
      
      * Registration enforcing strong passwords (#442) (ac64f553)
      * Custom branding for icon and text (#448) (081062cf)
      * Merge of /master into /dev - Baseline for Development (#509) (25c17487)
      * Updated Language Translations (#511) (b9f031e8)
      * Auto Announcements and Activity Log Expansion (#513) (323ba05c)
      * Level Import Fix (#514) (dc7c87c3)
      * Announcements Controls Rename (#515) (c5da9f78)
      * Set Default Scoring Cache Values (#516) (ec996a51)
      * Unique Logos Per Team # (#517) (6d4f9196)
      * Custom Branding Update (#518) (ea78f6ad)
      * Backup and Restore settings.ini on Tests (#519) (eb4a5b5e)
      * Maintain Team Protection on Database Reset (#520) (5d91ae92)
      * Fixed Login Form JS Bug (Fixes: #521) (#523) (2b1474bb)
      * Level Deletion Confirmation and Bug Fixes (#512) (4a7b5b52)
      * Provision Streamlined, Quick Setup Added, and Multiple Containers Support (#535) (b487fc11)
      * Merge branch 'dev' into WraySec/fbctf/merge@7f8c281
      3047351e
    • ubuntu's avatar
      Fixed conflict in Control · f7c64396
      ubuntu authored
      f7c64396
    • ubuntu's avatar
      Fixed conflict in ScoreLog · dd9de6e5
      ubuntu authored
      dd9de6e5
    • ubuntu's avatar
      Fixed conflict in ScoreLog · e181da25
      ubuntu authored
      e181da25
    • ubuntu's avatar
      Merge branch 'dev' into merge · 7f8c281f
      ubuntu authored
      Conflicts:
      	README.md
      	database/schema.sql
      	database/test_schema.sql
      	extra/run_tests.sh
      	extra/settings.ini.example
      	src/controllers/AdminController.php
      	src/controllers/Controller.php
      	src/language/lang_es.php
      	src/language/lang_hi.php
      	src/models/Level.php
      	src/models/ScoreLog.php
      	src/static/js/index.js
      7f8c281f
  11. Aug 04, 2017
    • Justin M. Wray's avatar
      Provision Streamlined, Quick Setup Added, and Multiple Containers Support (#535) · b487fc11
      Justin M. Wray authored
      * Separate docker containers per service
      
      * Provision Streamlined, Quick Setup Added, and Multiple Containers Support
      
      * The project now includes a number of "Quick Setup" options to ease the installation or startup process of the platform.  The following Quick Setup modes are available:
      
        *  Direct Installation - Used when directly installing to the system you are on; this is useful when installing on bare metal, an existing VM, or a cloud-based host.
      
            * `source ./extra/lib.sh`
            * `quick_setup install <dev/prod>`
      
        * Multi-Server Direct Installation - Used when directly installing the platform with each service on a separate system; this is useful when installing on bare metal systems, existing VMs, or cloud-based hosts.
      
          * Database Server (MySQL)
            * `source ./extra/lib.sh`
            * `quick_setup install_multi_mysql <dev/prod>`
      
          * Cache Server (Memcached)
            * `source ./extra/lib....
      b487fc11
  12. Aug 02, 2017
  13. Jun 22, 2017
    • Justin M. Wray's avatar
      Level Deletion Confirmation and Bug Fixes (#512) · 4a7b5b52
      Justin M. Wray authored
      * Level Deletion Confirmation and Bug Fixes
      
      * Added deletion confirmation dialog when deleting levels.
      
      * Level data is now deleted from HintLog, ScoresLog, and FailuresLog, when a level is deleted.
      
      * Cache invalidation performed on level deletion for records containing levels.
      
      * Moved all awaitable queries into a vector which are now executed via AsyncMysqlConnection::multiQuery().
      4a7b5b52
  14. Jun 07, 2017
    • Justin M. Wray's avatar
      Fixed Login Form JS Bug (Fixes: #521) (#523) · 2b1474bb
      Justin M. Wray authored
      * Login form JavaScript now properly retrieves and renders errors when invalid login credentials are provided.
      
      * Added teamLoginFormError() distinguished from teamNameFormError() and teamTokenFormError().
      
      * Updated teamPasswordFormError() to read the login AJAX response and call the appropriate error function.
      
      * This PR fixes the bug identified in Issue #521.
      2b1474bb
    • Justin M. Wray's avatar
      Maintain Team Protection on Database Reset (#520) · 5d91ae92
      Justin M. Wray authored
      * Maintain Team Protection on Database Reset
      
      * Database resets, through Admin Control, will maintain protection on protected admin accounts.
      
      * Added Team::genSetProtected() to set protection status on a team.
      
      * Database reset now calls Team::genSetProtected() on previous protected accounts.
      
      * The Database reset process has been optimized to improve performance.
      
      * Fixed Permissions
      5d91ae92
    • Justin M. Wray's avatar
      Backup and Restore settings.ini on Tests (#519) · eb4a5b5e
      Justin M. Wray authored
      * If `settings.ini` exists it will now be copied to `settings.ini.bak` during the testing process (/extra/run_tests.sh).
      
      * After the tests complete, if the backup file exists it will restore the file.
      eb4a5b5e
    • Justin M. Wray's avatar
      Custom Branding Update (#518) · ea78f6ad
      Justin M. Wray authored
      * Added "Custom Organization," editable within the administrative interface. The organization will display as the system name (i.e., "Custom CTF") in all relevant locations including the page titles.
      
      * Custom Text has been renamed to "Custom Byline."
      
      * The custom organization value will also be used for the welcome message on the landing page.
      
      * Database updated to support the new customization options.
      ea78f6ad
    • Justin M. Wray's avatar
      Unique Logos Per Team # (#517) · 6d4f9196
      Justin M. Wray authored
      * Functionality prevents users from utilizing the same logo as another user/team or one already in use.
      
      * Users now are provided the option of selecting a unique, or unused logo.
      
      * When a logo is selected the logo is marked as used.
      
      * When a logo is removed from a team (through team deletion, logo change, or otherwise) the logo is readded to the rotation for available logos.
      
      * When a team is imported their logo is set to used.
      
      * Database schema changed to set the default for all logos to unused. The scheme update also sets the admin logo to used.
      6d4f9196
    • Justin M. Wray's avatar
      Set Default Scoring Cache Values (#516) · ec996a51
      Justin M. Wray authored
      * Before a game begins, or before any scores are captured, the Memcached is empty for multiple scoring values. This results in continual hits to the database.
      
      * Scores are now cached at zero until the first capture is obtained.   This dramatically reduces the number of queries performed and the load on the server.
      ec996a51
    • Justin M. Wray's avatar
      Announcements Controls Rename (#515) · c5da9f78
      Justin M. Wray authored
      * Renamed "Game Controls" to "Announcement Controls" on the administrative Announcement page.
      c5da9f78
    • Justin M. Wray's avatar
      Level Import Fix (#514) · dc7c87c3
      Justin M. Wray authored
      * Added backward compatibility to the Level import process for exported files prior to PR #451
      
      * Levels exported after PR #451 contain Links and Attachments, however prior to PR #451 they did not.  The import code will now import levels even if the import file doesn't contain Links or Attachments.
      dc7c87c3
    • Justin M. Wray's avatar
      Auto Announcements and Activity Log Expansion (#513) · 323ba05c
      Justin M. Wray authored
      * Dynamically generate activity log and store in the database. Activity log table stores the object type and identifier, so the log is up to date even if some portion of the object has changed (i.e., name).
      
      * Optionally, allow for game related activites to be automatically announced through the announcements area.
      
      * Added table "activity_log" to database.
      
      * Added column "auto_announce" into database configuration table.
      
      * Added auto announcement toggle in admin panel.
      
      * Added auto announcement and activity logging for:
        * Game Start, Pause, Resume, and End
        * Levels being Added, Updated, Enabled, Disabled
      
      * Added activity logging for levels being captured.
      
      * Added ActivityLog class:
        * genCaptureLog() - Stores level capture event in activity log
        * genCreateGameActionLog() - Stores a change to the game state
        * genAdminLog() - Stores administrative action
        * genCreateGenericLog() - Stores generic messages
        * genCreate() - Manually create activity log entry
      
      * Invalidated memcached for relevant level actions.
      
      * Cleanly exit the ActivityLog class if a user session doesn't exist.
      
      * Fixed a variable name mismatch in the Level class.
      
      * The Auto Announcement feature, now call from numerous administrative methods, requires the "game" and "auto_announce" configuration values.  Both configuration values have been added to the seed data.
      
      * The configuration test asserts have been updated to match the new record counts.
      
      * The testSetStatus() test case to use the second (undeleted) level.
      323ba05c
    • Justin M. Wray's avatar
      Updated Language Translations (#511) · b9f031e8
      Justin M. Wray authored
      * All languages have been updated to include missing translations.
      
      * Primarily this will declutter the error log, making debugging far easier.
      b9f031e8
  15. Jun 06, 2017
    • Justin M. Wray's avatar
      Merge of /master into /dev - Baseline for Development (#509) · 25c17487
      Justin M. Wray authored
      * add hindi translation
      
      * added hindi translation
      
      * Update lang_hi.php
      
      * Error Checking During Build Tests (#452)
      
      * Error Checking During Build Tests
      
      * Execute hh_client during build tests.
      
      * Currently the PHP built-in getimagesizefromstring function is not in the HHVM upstream hhi, and therefore generates an error.  In the future, once getimagesizefromstring is added upstream, we should use the hh_client exit status.
      
      * * Readded execute permissions to the script.
      
      * HHVM/Hack Typing Error Fixes (#450)
      
      * HHVM/Hack Typing Error Fixes
      
      * Fixed a few HHVM/Hack typing and strict compliance issues.
      
      * This is necessary before hh_client can run and be enforced during the build process. (See comments on #435)
      
      * * Updated formatting.
      
      * Require bxslider version 4.2.6 (Fixes #455) (#458)
      
      * This resolves a current build error #455.
      
      * bxslider was updated from 4.2.6 to 4.2.7 on February 14th.  Previously FBCTF allowed for a near match to 4.2.6.  However, FBCTF fails to build with 4.2.7.  During the installation, process grunt failed to build the browserify javascript.
      
      * Fixed Syntax Errors in Hindi Language (Fixes Build Errors) (#460)
      
      * Fixed minor syntax error due to character encoding.
      
      * This will ensure the project builds (no Hack errors).
      
      * Automated Game Start and Stop (#449)
      
      * Automated Game Start and Stop
      
      * Games will automatically start and stop at their scheduled times.  Administrators can still manually start or stop a game regardless of the configured schedule.
      
      * Both Control::genAutoBegin() and Control::genAutoEnd() were added to check the current time against the scheduled start or stop time and perform the relevant action (Control::genBegin or Control::getEnd).
      
      * Control::genAutoRun() checks the current game status and determine if the game should be starting or ending, calling the appropriate function (Control::genAutoBegin or Control::getAutoEnd) and is exclusively used in the new autorun.php script.
      
      * Control::genRunAutoRunScript() runs the new autorun.php script, ensuring the script is not already running before starting a new copy.
      
      * The Router class was updated to include a call to Control::genRunAutoRunScript(), this ensures the script is always running.  This script status check, and execution when needed, only takes place on a full page load.
      
      * The autorun.php script runs Control::genAutoRun() and sleeps up to 30 seconds.
      
      * If the game is scheduled to start or stop within 30 seconds, the script will sleep for the necessary amount of time.
      
      * Games will always start with at most a 29-second difference from the scheduled time.  This discrepancy can only take place if the schedule is changed within 30 seconds of the previously scheduled time.  Otherwise, the execution will happen at the scheduled time.
      
      * This automation is self-contained and requires no additional dependencies or external services (like cron, etc.).
      
      * * Allow administrators to define the cycle time (in seconds) for the autorun process.  This time will be used for the sliding sleep.
      
      * * Added sanitization to the autorun script path/file.
      
      * Attachments and Links Import/Export, Database Restore, and Control Cleanup (#451)
      
      * Attachments and Links Import/Export, Database Restore, and Control Cleanup
      
      * Attachments can now be exported and imported.  On export, attachments are downloaded into a Tar Gzip and securely extracted on import.
      
      * Links and Attachments data is now provided within the Levels export.  Users must import both the Level data and the Attachment files to restore the levels with attachments.
      
      * A database restore option has been added which utilizes the backed up database content.  This overwrites all data in the database.
      
      * The Control page has been reorganized to align the various functionality better.
      
      * Memcached flushing has been added to all relevant data imports.
      
      * Error handling has been added to the various import functions.
      
      * * Removed getter function for the Attachment constant.
      
      * Switched double quotes with single quotes.
      
      * Update README.md
      
      * Update README.md
      
      * Update README.md
      
      * Update README.md
      
      * Live Sync API (#459)
      
      * Live Sync API
      
      * Introducing the Live Sync API.
      
      * The Live Sync API allows administrators to import game activity in near-real-time.  Users can link their accounts on one or more FBCTF platform instances and their scores will be automatically imported into the systems that have been linked.
      
      * The primary use-case revolves around event aggregation across multiple FBCTF instances.  Event organizers can now separate FBCTF instances and combine scores into one global scoreboard.
      
      * The Live Sync API will import Levels, Categories, Scoring Events, and Hint Usage.  Scores are automatically calculated, and bonuses are updated to ensure accurate scoring across linked FBCTF instances.
      
      * Administrators determine which systems, if any, are linked.
      
      * Users must link their account in order for their activity to be synced.
      
      * The UI/UX of FBCTF has been updated to include a mechanism for users to configure their Live Sync credentials.
      
      * Users cannot obtain hints or capture levels on the importing system.
      
      * The API is JSON based and the schema is generalized so that it can leveraged by other platforms or external processes.  So data can be synced from non-FBCTF platforms.
      
      * The importing script will automatically handle country conflicts (if two systems have the same country selected for a level).
      
      * USER GUIDE (Documentation):
      
        * Users must first have an account on all FBCTF instances they wish to link.
      
        * The user must then login and access the game board.
      
        * From the navigation menu, the user should select "Account."
      
        * The user must then set a Live Sync username and password.  The Live Sync username and password must not be their login credentials.  In fact, users are prohibited from using their account password as their Live Sync password.
      
        * The user would repeat the above steps for each FBCTF instance they wish to link.  The Live Sync credentials must be the same on each FBCTF instance or their accounts will not be linked.
      
      * ADMIN GUIDE (Documentation):
      
        * The admin is free to sync as many platforms as their desire.  Additionally the admin may import from as many API sources as their desire.
      
        * The admin will need to launch the "live import" script, on any importing systems, from the command-line:
      
          * `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php <Space Delimited URLs to API Endpoints> <Sleep Between Cycles> <Disable SSL Certificate Verification> <Show Debug Messages>`
      
          * Disabling of the SSL Verification and Debugging are both optional.  The URL(s) and Sleep time are required arguments.
      
          * EXAMPLE:  `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php "https://10.10.10.101/data/livesync.php https://10.10.10.102/data/livesync.php https://10.10.10.103/other/platform/api" 300 true true`
      
      * API SCHEMA (JSON):
      
        * JSON:
      
      [{"active":true,"type":"flag","title":"Example Level 1","description":"This is the first example level.","entity_iso_code":"TJ","category":"None","points":100,"bonus":30,"bonus_dec":10,"penalty":10,"teams":{"fbctf:user1:$2y$12$a1T4KyqqxADi3YIJ7M2sf.VoSHz6qMBx.zrxAIvZnD8de95EsLeny":{"timestamp":"2017-02-17 02:20:22","capture":true,"hint":false}}}]
      
        * Explained (Formatted output for readability - the actually data must be in valid JSON format):
      
          [0] => Array
              (
                  [active] => 1						// Level Status (Enabled/Disabled)
                  [type] => flag						// Level Type (Flag or Quiz)
                  [title] => Example Level 1				// Level Name
                  [description] => This is the first example level.	// Level Description
                  [entity_iso_code] => US					// Country Code (Mapping)
                  [category] => None						// Level Category
                  [points] => 100						// Points
                  [bonus] => 30						// Bonus Points
                  [bonus_dec] => 10						// Bonus Point Decrement
                  [penalty] => 0						// Hint Cost
                  [teams] => Array
                      (
                          [fbctf:user3:$2y$12$GIR7V0Q2OMDv8cTTOnzKVpGYgR4.pWTsPRHtZ3yenKZ9JxOabx4m2] => Array	// Live Sync Type, Live Sync Username, Live Sync Key (Hash)
                              (
                                  [timestamp] => 2017-02-17 01:09:24						// Activity Timestamp
                                  [capture] => 1									// Capture Status
                                  [hint] => 									// Hint Used
                              )
      
                      )
      
              )
      
        * Example (Formatted output for readability - the actually data must be in valid JSON format):
      
      Array
      (
          [0] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 1
                  [description] => This is the first example level.
                  [entity_iso_code] => US
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                      )
      
              )
      
          [1] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 2
                  [description] => This is the second example level.
                  [entity_iso_code] => OM
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                          [fbctf:user1:$2y$12$n.VmlNNwxmZ/OkGGuhVhFeX0VExAgjoaYzyetLCIemSXN/yxWXLyO] => Array
                              (
                                  [timestamp] => 2017-02-17 01:01:49
                                  [capture] => 1
                                  [hint] => 1
                              )
      
                          [fbctf:user2:$2y$12$GIDv8cR7V0nzKVpQ2OMTTOGYgR4.pWTxOPRH9abtsJZ3yenKZx4m2] => Array
                              (
                                  [timestamp] => 2017-02-17 01:21:13
                                  [capture] => 1
                                  [hint] => 1
                              )
      
                      )
      
              )
      
          [2] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 3
                  [description] => This is the third example level.
                  [entity_iso_code] => MA
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                          [fbctf:user2:$2y$12$GIDv8cR7VpQ2OM0nzKVTTOGYgR4.pWTxOabtsPRH9JZ3yenKZx4m2] => Array
                              (
                                  [timestamp] => 2017-02-17 01:18:45
                                  [capture] => 1
                                  [hint] =>
                              )
      
                          [fbctf:user1:$2y$12$n.VmlNNwxmZ/OkGGuhVhFeXYzExAg0VoajyetLCIemSXN/yxWXLyO] => Array
                              (
                                  [timestamp] => 2017-02-17 01:01:41
                                  [capture] => 1
                                  [hint] =>
                              )
      
                      )
      
              )
      
          [3] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 4
                  [description] => This is the second example level.
                  [entity_iso_code] => RO
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                          [fbctf:user3:$2y$12$GIDv8cR7V02OnzKVpQMTTOGYgR4.pWTsPOabtZRH9Jx3yenKZx4m2] => Array
                              (
                                  [timestamp] => 2017-02-17 01:09:24
                                  [capture] => 1
                                  [hint] =>
                              )
      
                      )
      
              )
      
      )
      
      * TO DO (Enhancements):
      
        * Implemented alternative Live Sync key/authentication mechanisms, such as: Facebook Login, OAuth, etc.
      
        * Improve the processing of Bases/Progressive scoring.
      
        * Integrate password strength enforcement for the Live Sync credentials.
      
      * * Added unit tests for Live Sync to TeamTest
      
      * * Updated unit tests for the Live Sync API.
      
      * Added Google OAuth to Live Sync API
      
      * Google OAuth can now be used with the Live Sync when the exporting system provides the "google_oauth" type and provides the email address of the user in base64 encoded form.
      
      * Added Google OAuth UI/UX.  If enabled, this allows a user to link their Google account to their FBCTF account using Google OAuth.  The user simply navigates to the account page and clicks the "Link Your Google Account" button and completes the sign-in/authorization process.
      
      * Administrators must enable Google OAuth.  When disabled the option does not appear for the users.  To enable Google OAuth the administrator must first create a Google API account and then place the API secrets file on the system (in a non-web directory).  The administrator would then set the full path to the API secrets file in the settings.ini file, within the GOOGLE_OAUTH_FILE field.
      
      * The Live Sync API has been updated to handle the "google_oauth" type case.
      
      * The liveimport.php script has been updated to set default values for some of the API fields.  The following fields are mandatory:
      
        * title
      
        * description
      
        * points
      
        * teams
      
      * The live import code has also been updated to ensure duplicate levels, when using a combination of non-defined and defined countries, are not generated.
      
      * The project now requires google/apiclient ^2.0 from composer.  Updated composer.json and composer.lock to define the new dependencies.
      
      * Minor formatting updates.
      
      * * Ensure mandatory fields are set, gracefully skip when they are not.
      
      * Refined Live Import CLI Options and Updated Google OAuth Data
      
      * The live sync import script (livesync.php) now utilizes `getopts()` to provide more user-friendly option input to the command-line script.  The script will provide a help message upon usage without the required field(s).  Here is the help message text:
      
      ```
      Usage:
        hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php
          --url <Sync URL> [Switched allowed multiple times.  Optionally provide custom HTTP headers after URL, pipe delimited]
          --sleep <Time to Sleep Between Cycles> [Default: 300]
          --disable-ssl-verification [Optional: Disables SSL Certification Verification]
          --debug [Optional: Enables Debug Output]
      ```
      
      * Custom HTTP Headers are now supported via the `url` CLI argument, using a pipe (`|`) delimiter.  Multiple headers may be provided by the user.
      
      * Users of the live sync import script (livesync.php) must provide at minimum the `url` argument.  Multiple URLs are allowed in order to import from more than one host.  Additionally, users may specify custom HTTP headers as necessary per-URL.
      
      * The `sleep`, `disable-ssl-verification`, and `debug` arguments are optional.  By default the script will sleep for 300 seconds between imports; this may be changed with the `sleep` option.  By default the script will enforce SSL security and verification, however there are times when this may need to be disabled.  SSL Verification can be disabled with the `disable-ssl-verification` option.  The `debug` option provides a detailed output of the scripts activity; unless `debug` is used, the script will provide no output unless an error is encountered.
      
      * Here are some example usages of the liveimport.php script:
      
        * Single URL, 30 second cycles:
      
      `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --url "https://10.10.10.101/data/livesync.php" --sleep 30`
      
        * Multiple URLs, 90 second cycles, Disable SSL Verification:
      
      `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --disable-ssl-verification --url "https://10.10.10.101/data/livesync.php" --url "https://10.10.10.103/data/livesync.php" --sleep 90`
      
        * Multiple URLs, One Custom HTTP Header, Debug Enabled:
      
      `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --debug --url "https://10.10.10.101/data/livesync.php" --url "https://10.10.10.102/data/livesync.php|X-API-KEY: f4f0d2154f338fd8edb38fc3839f22dd"`
      
      * The live sync import script (livesync.php) now performs XSSI filtering on the returned JSON and logs an error message if the JSON data is missing or malformed.
      
      * Inverse conditions within the live sync import script (livesync.php) have been reformatted to provide clearer readability.
      
      * The Google OAuth Live Sync key has been switched from the user's email address to their Google Profile ID.  This value does not need to be encoded.
      
      * Minor Updates
      
      * Added a specific redirect URL for the Google OAuth process.  This will ensure the user is redirected back to the same (sub)domain they came from.  This is primarily useful if the FBCTF instance is accessible from multiple domains or subdomains (like www).  The redirect URL must still be authorized in the Google API settings/console.
      
      * Added a date/time output for the debug mode of the live import script.
      
      * Set the modal title to a static value.
      
      * I think its bad (#446)
      
      * Fix fail error
      
      * Order by name in category list
      
      The category filter in gameboard aren't ordered alphabetically
      
      * Autofocus in team name
      
      * Fail
      
      * Fix Fail autofocus
      
      * Fix error with autofocus
      
      * Not very good
      
      For security reasons, I think it's not very good insert the admin id by default at session table
      
      * Update SessionTest.php
      
      * Updated LiveSync Security (#494)
      
      * Updated LiveSync Security
      
      * Live Sync API is now disabled by default.
      
      * Admins can enable or disable the Live Sync API from the Administration Configuration page.
      
      * Live Sync API now has an optional 'Auth Key.'  When the auth key is set, anyone attempting to pull from the API must supply the auth key value in their request.  Without the auth key, no data is provided by the Live Sync API endpoint.
      
      * When using the Auth Key, it must be added as a parameter to the URL value in the `liveimport` script: ```?auth=XXXXX_```
      
        * Example (with an auth key of `1234567890`:
      
        * `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --url 'https://10.10.10.101/data/livesync.php?auth=1234567890'`
      
        * Note:  When using the Auth Key you should use a secure key.
      
      * The `livesync` API endpoint will provide error messages if the API is disabled, the key is missing or invalid, or if any general error is encountered.
      
      * The `liveimport` script will check for errors and display those in the output if any are encountered.
      
      * Updated LiveSync Security
      
      * Combined Awaitables throughout LiveSync endpoint.
      
      * Used hash_equals() for API key verification, mitigating timing attacks on the key.# Please enter the commit message for your changes. Lines starting
      
      * Temp fix for issue 499 & 500.  Forcing Grunt to continue as it is not correctly detecting node_modules in the folder (#502)
      
      * Merge Deconflict of /dev and /master (#503)
      
      * Registration enforcing strong passwords (#442)
      
      * Password types in admin
      
      * Fully functional password complexity enforcement for registration
      
      * lowercase word in text
      
      * Adding test for password types regex and fixing all errors for hh_client
      
      * Updating outdated schema for tests
      
      * Custom branding for icon and text (#448)
      
      * Custom branding for icon and text
      
      * Replace async calls branding xhp by attributes
      
      * Use genRenderBranding in genRenderMobilePage and combine awaitables
      25c17487
  16. May 20, 2017
    • Justin M. Wray's avatar
      Merge Deconflict of /dev and /master (#503) · 51e06a70
      Justin M. Wray authored
      * Registration enforcing strong passwords (#442)
      
      * Password types in admin
      
      * Fully functional password complexity enforcement for registration
      
      * lowercase word in text
      
      * Adding test for password types regex and fixing all errors for hh_client
      
      * Updating outdated schema for tests
      
      * Custom branding for icon and text (#448)
      
      * Custom branding for icon and text
      
      * Replace async calls branding xhp by attributes
      
      * Use genRenderBranding in genRenderMobilePage and combine awaitables
      51e06a70
  17. May 19, 2017
  18. May 08, 2017
    • Justin M. Wray's avatar
      Updated LiveSync Security (#494) · e880251b
      Justin M. Wray authored
      * Updated LiveSync Security
      
      * Live Sync API is now disabled by default.
      
      * Admins can enable or disable the Live Sync API from the Administration Configuration page.
      
      * Live Sync API now has an optional 'Auth Key.'  When the auth key is set, anyone attempting to pull from the API must supply the auth key value in their request.  Without the auth key, no data is provided by the Live Sync API endpoint.
      
      * When using the Auth Key, it must be added as a parameter to the URL value in the `liveimport` script: ```?auth=XXXXX_```
      
        * Example (with an auth key of `1234567890`:
      
        * `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --url 'https://10.10.10.101/data/livesync.php?auth=1234567890'`
      
        * Note:  When using the Auth Key you should use a secure key.
      
      * The `livesync` API endpoint will provide error messages if the API is disabled, the key is missing or invalid, or if any general error is encountered.
      
      * The `liveimport` script will check for errors and display those in the output if any are encountered.
      
      * Updated LiveSync Security
      
      * Combined Awaitables throughout LiveSync endpoint.
      
      * Used hash_equals() for API key verification, mitigating timing attacks on the key.# Please enter the commit message for your changes. Lines starting
      e880251b
  19. Mar 22, 2017
    • @ShargonXL's avatar
      I think its bad (#446) · d3265647
      @ShargonXL authored
      * Fix fail error
      
      * Order by name in category list
      
      The category filter in gameboard aren't ordered alphabetically
      
      * Autofocus in team name
      
      * Fail
      
      * Fix Fail autofocus
      
      * Fix error with autofocus
      
      * Not very good
      
      For security reasons, I think it's not very good insert the admin id by default at session table
      
      * Update SessionTest.php
      d3265647
    • Justin M. Wray's avatar
      Live Sync API (#459) · 0b7ca09a
      Justin M. Wray authored
      * Live Sync API
      
      * Introducing the Live Sync API.
      
      * The Live Sync API allows administrators to import game activity in near-real-time.  Users can link their accounts on one or more FBCTF platform instances and their scores will be automatically imported into the systems that have been linked.
      
      * The primary use-case revolves around event aggregation across multiple FBCTF instances.  Event organizers can now separate FBCTF instances and combine scores into one global scoreboard.
      
      * The Live Sync API will import Levels, Categories, Scoring Events, and Hint Usage.  Scores are automatically calculated, and bonuses are updated to ensure accurate scoring across linked FBCTF instances.
      
      * Administrators determine which systems, if any, are linked.
      
      * Users must link their account in order for their activity to be synced.
      
      * The UI/UX of FBCTF has been updated to include a mechanism for users to configure their Live Sync credentials.
      
      * Users cannot obtain hints or capture levels on the importing system.
      
      * The API is JSON based and the schema is generalized so that it can leveraged by other platforms or external processes.  So data can be synced from non-FBCTF platforms.
      
      * The importing script will automatically handle country conflicts (if two systems have the same country selected for a level).
      
      * USER GUIDE (Documentation):
      
        * Users must first have an account on all FBCTF instances they wish to link.
      
        * The user must then login and access the game board.
      
        * From the navigation menu, the user should select "Account."
      
        * The user must then set a Live Sync username and password.  The Live Sync username and password must not be their login credentials.  In fact, users are prohibited from using their account password as their Live Sync password.
      
        * The user would repeat the above steps for each FBCTF instance they wish to link.  The Live Sync credentials must be the same on each FBCTF instance or their accounts will not be linked.
      
      * ADMIN GUIDE (Documentation):
      
        * The admin is free to sync as many platforms as their desire.  Additionally the admin may import from as many API sources as their desire.
      
        * The admin will need to launch the "live import" script, on any importing systems, from the command-line:
      
          * `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php <Space Delimited URLs to API Endpoints> <Sleep Between Cycles> <Disable SSL Certificate Verification> <Show Debug Messages>`
      
          * Disabling of the SSL Verification and Debugging are both optional.  The URL(s) and Sleep time are required arguments.
      
          * EXAMPLE:  `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php "https://10.10.10.101/data/livesync.php https://10.10.10.102/data/livesync.php https://10.10.10.103/other/platform/api" 300 true true`
      
      * API SCHEMA (JSON):
      
        * JSON:
      
      [{"active":true,"type":"flag","title":"Example Level 1","description":"This is the first example level.","entity_iso_code":"TJ","category":"None","points":100,"bonus":30,"bonus_dec":10,"penalty":10,"teams":{"fbctf:user1:$2y$12$a1T4KyqqxADi3YIJ7M2sf.VoSHz6qMBx.zrxAIvZnD8de95EsLeny":{"timestamp":"2017-02-17 02:20:22","capture":true,"hint":false}}}]
      
        * Explained (Formatted output for readability - the actually data must be in valid JSON format):
      
          [0] => Array
              (
                  [active] => 1						// Level Status (Enabled/Disabled)
                  [type] => flag						// Level Type (Flag or Quiz)
                  [title] => Example Level 1				// Level Name
                  [description] => This is the first example level.	// Level Description
                  [entity_iso_code] => US					// Country Code (Mapping)
                  [category] => None						// Level Category
                  [points] => 100						// Points
                  [bonus] => 30						// Bonus Points
                  [bonus_dec] => 10						// Bonus Point Decrement
                  [penalty] => 0						// Hint Cost
                  [teams] => Array
                      (
                          [fbctf:user3:$2y$12$GIR7V0Q2OMDv8cTTOnzKVpGYgR4.pWTsPRHtZ3yenKZ9JxOabx4m2] => Array	// Live Sync Type, Live Sync Username, Live Sync Key (Hash)
                              (
                                  [timestamp] => 2017-02-17 01:09:24						// Activity Timestamp
                                  [capture] => 1									// Capture Status
                                  [hint] => 									// Hint Used
                              )
      
                      )
      
              )
      
        * Example (Formatted output for readability - the actually data must be in valid JSON format):
      
      Array
      (
          [0] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 1
                  [description] => This is the first example level.
                  [entity_iso_code] => US
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                      )
      
              )
      
          [1] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 2
                  [description] => This is the second example level.
                  [entity_iso_code] => OM
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                          [fbctf:user1:$2y$12$n.VmlNNwxmZ/OkGGuhVhFeX0VExAgjoaYzyetLCIemSXN/yxWXLyO] => Array
                              (
                                  [timestamp] => 2017-02-17 01:01:49
                                  [capture] => 1
                                  [hint] => 1
                              )
      
                          [fbctf:user2:$2y$12$GIDv8cR7V0nzKVpQ2OMTTOGYgR4.pWTxOPRH9abtsJZ3yenKZx4m2] => Array
                              (
                                  [timestamp] => 2017-02-17 01:21:13
                                  [capture] => 1
                                  [hint] => 1
                              )
      
                      )
      
              )
      
          [2] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 3
                  [description] => This is the third example level.
                  [entity_iso_code] => MA
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                          [fbctf:user2:$2y$12$GIDv8cR7VpQ2OM0nzKVTTOGYgR4.pWTxOabtsPRH9JZ3yenKZx4m2] => Array
                              (
                                  [timestamp] => 2017-02-17 01:18:45
                                  [capture] => 1
                                  [hint] =>
                              )
      
                          [fbctf:user1:$2y$12$n.VmlNNwxmZ/OkGGuhVhFeXYzExAg0VoajyetLCIemSXN/yxWXLyO] => Array
                              (
                                  [timestamp] => 2017-02-17 01:01:41
                                  [capture] => 1
                                  [hint] =>
                              )
      
                      )
      
              )
      
          [3] => Array
              (
                  [active] => 1
                  [type] => flag
                  [title] => Example Level 4
                  [description] => This is the second example level.
                  [entity_iso_code] => RO
                  [category] => None
                  [points] => 100
                  [bonus] => 30
                  [bonus_dec] => 10
                  [penalty] => 0
                  [teams] => Array
                      (
                          [fbctf:user3:$2y$12$GIDv8cR7V02OnzKVpQMTTOGYgR4.pWTsPOabtZRH9Jx3yenKZx4m2] => Array
                              (
                                  [timestamp] => 2017-02-17 01:09:24
                                  [capture] => 1
                                  [hint] =>
                              )
      
                      )
      
              )
      
      )
      
      * TO DO (Enhancements):
      
        * Implemented alternative Live Sync key/authentication mechanisms, such as: Facebook Login, OAuth, etc.
      
        * Improve the processing of Bases/Progressive scoring.
      
        * Integrate password strength enforcement for the Live Sync credentials.
      
      * * Added unit tests for Live Sync to TeamTest
      
      * * Updated unit tests for the Live Sync API.
      
      * Added Google OAuth to Live Sync API
      
      * Google OAuth can now be used with the Live Sync when the exporting system provides the "google_oauth" type and provides the email address of the user in base64 encoded form.
      
      * Added Google OAuth UI/UX.  If enabled, this allows a user to link their Google account to their FBCTF account using Google OAuth.  The user simply navigates to the account page and clicks the "Link Your Google Account" button and completes the sign-in/authorization process.
      
      * Administrators must enable Google OAuth.  When disabled the option does not appear for the users.  To enable Google OAuth the administrator must first create a Google API account and then place the API secrets file on the system (in a non-web directory).  The administrator would then set the full path to the API secrets file in the settings.ini file, within the GOOGLE_OAUTH_FILE field.
      
      * The Live Sync API has been updated to handle the "google_oauth" type case.
      
      * The liveimport.php script has been updated to set default values for some of the API fields.  The following fields are mandatory:
      
        * title
      
        * description
      
        * points
      
        * teams
      
      * The live import code has also been updated to ensure duplicate levels, when using a combination of non-defined and defined countries, are not generated.
      
      * The project now requires google/apiclient ^2.0 from composer.  Updated composer.json and composer.lock to define the new dependencies.
      
      * Minor formatting updates.
      
      * * Ensure mandatory fields are set, gracefully skip when they are not.
      
      * Refined Live Import CLI Options and Updated Google OAuth Data
      
      * The live sync import script (livesync.php) now utilizes `getopts()` to provide more user-friendly option input to the command-line script.  The script will provide a help message upon usage without the required field(s).  Here is the help message text:
      
      ```
      Usage:
        hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php
          --url <Sync URL> [Switched allowed multiple times.  Optionally provide custom HTTP headers after URL, pipe delimited]
          --sleep <Time to Sleep Between Cycles> [Default: 300]
          --disable-ssl-verification [Optional: Disables SSL Certification Verification]
          --debug [Optional: Enables Debug Output]
      ```
      
      * Custom HTTP Headers are now supported via the `url` CLI argument, using a pipe (`|`) delimiter.  Multiple headers may be provided by the user.
      
      * Users of the live sync import script (livesync.php) must provide at minimum the `url` argument.  Multiple URLs are allowed in order to import from more than one host.  Additionally, users may specify custom HTTP headers as necessary per-URL.
      
      * The `sleep`, `disable-ssl-verification`, and `debug` arguments are optional.  By default the script will sleep for 300 seconds between imports; this may be changed with the `sleep` option.  By default the script will enforce SSL security and verification, however there are times when this may need to be disabled.  SSL Verification can be disabled with the `disable-ssl-verification` option.  The `debug` option provides a detailed output of the scripts activity; unless `debug` is used, the script will provide no output unless an error is encountered.
      
      * Here are some example usages of the liveimport.php script:
      
        * Single URL, 30 second cycles:
      
      `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --url "https://10.10.10.101/data/livesync.php" --sleep 30`
      
        * Multiple URLs, 90 second cycles, Disable SSL Verification:
      
      `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --disable-ssl-verification --url "https://10.10.10.101/data/livesync.php" --url "https://10.10.10.103/data/livesync.php" --sleep 90`
      
        * Multiple URLs, One Custom HTTP Header, Debug Enabled:
      
      `hhvm -vRepo.Central.Path=/var/run/hhvm/.hhvm.hhbc_liveimport /var/www/fbctf/src/scripts/liveimport.php --debug --url "https://10.10.10.101/data/livesync.php" --url "https://10.10.10.102/data/livesync.php|X-API-KEY: f4f0d2154f338fd8edb38fc3839f22dd"`
      
      * The live sync import script (livesync.php) now performs XSSI filtering on the returned JSON and logs an error message if the JSON data is missing or malformed.
      
      * Inverse conditions within the live sync import script (livesync.php) have been reformatted to provide clearer readability.
      
      * The Google OAuth Live Sync key has been switched from the user's email address to their Google Profile ID.  This value does not need to be encoded.
      
      * Minor Updates
      
      * Added a specific redirect URL for the Google OAuth process.  This will ensure the user is redirected back to the same (sub)domain they came from.  This is primarily useful if the FBCTF instance is accessible from multiple domains or subdomains (like www).  The redirect URL must still be authorized in the Google API settings/console.
      
      * Added a date/time output for the debug mode of the live import script.
      
      * Set the modal title to a static value.
      0b7ca09a
  20. Mar 18, 2017