text:
'use strict';

const debug = require('debuglog')('simple-oracledb');
const asyncLib = require('async');
const Connection = require('./connection');
const extensions = require('./extensions');
const emitter = require('./emitter');
const promiseHelper = require('./promise-helper');
const constants = require('./constants');

let poolIDCounter = 0;

/**
 * Holds query invocation definitions.
 *
 * @typedef {Object} QuerySpec
 * @param {String} sql - The SQL to execute
 * @param {Object} [bindParams] - Optional bind parameters
 * @param {Object} [options] - Optional query options
 */

/**
 * This events is triggered when a connection is created via pool.
 *
 * @event Pool#connection-created
 * @param {Connection} connection - The connection instance
 */

/**
 * This events is triggered when a connection is released successfully.
 *
 * @event Pool#connection-released
 * @param {Connection} connection - The connection instance
 */

/**
 * This events is triggered after the pool is released successfully.
 *
 * @event Pool#release
 */

/*jslint debug: true */
/*istanbul ignore next*/
/**
 * This class holds all the extended capabilities added the oracledb pool.
 *
 * @author Sagie Gur-Ari
 * @class Pool
 * @public
 * @fires event:connection-created
 * @fires event:connection-released
 * @fires event:release
 */
function Pool() {
    //should not be called
}
/*jslint debug: false */

/**
 * Marker property.
 *
 * @member {Boolean}
 * @alias Pool.simplified
 * @memberof! Pool
 * @public
 */
Pool.prototype.simplified = true;

/**
 * Sets up events based on connection events.
 *
 * @function
 * @memberof! Pool
 * @private
 * @param {Connection} connection - The connection object
 */
Pool.prototype.setupEvents = function (connection) {
    const self = this;

    if (connection) {
        connection.once('release', function onRelease() {
            self.emit('connection-released', connection);
        });

        self.emit('connection-created', connection);
    }
};

/*eslint-disable valid-jsdoc*/
//jscs:disable jsDoc
/**
 * Wraps the original oracledb getConnection in order to provide an extended connection object.

 * In addition, this function will attempt to fetch a connection from the pool and in case of any error will reattempt for a configurable amount of times.

 * It will also ensure the provided connection is valid by running a test SQL and if validation fails, it will fetch another connection (continue to reattempt).

 * See [getConnection](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#getconnectionpool) for official API details.

 * See [createPool](https://github.com/sagiegurari/simple-oracledb/blob/master/docs/api.md#SimpleOracleDB.oracle.createPool) for extended createPool API details.
 *
 * @function
 * @memberof! Pool
 * @public
 * @param {AsyncCallback} [callback] - Invoked with an error or an extended connection object
 * @returns {Promise} In case of no callback provided in input, this function will return a promise
 * @fires event:connection-created
 * @example
 * ```js
 * oracledb.createPool({
 *   retryCount: 5, //The max amount of retries to get a connection from the pool in case of any error (default to 10 if not provided)
 *   retryInterval: 500, //The interval in millies between get connection retry attempts (defaults to 250 millies if not provided)
 *   runValidationSQL: true, //True to ensure the connection returned is valid by running a test validation SQL (defaults to true)
 *   usePingValidation: true, //If runValidationSQL, this flag will define if validation should first attempt to use connection.ping instead of running a SQL
 *   validationSQL: 'SELECT 1 FROM DUAL', //The test SQL to invoke before returning a connection to validate the connection is open (defaults to 'SELECT 1 FROM DUAL')
 *   //any other oracledb pool attributes
 * }, function onPoolCreated(error, pool) {
 *   pool.getConnection(function onConnection(poolError, connection) {
 *     //continue flow (connection, if provided, has been tested to ensure it is valid)
 *   });
 * });
 *
 * //another example but with promise support
 * oracledb.createPool({
 *   retryCount: 5, //The max amount of retries to get a connection from the pool in case of any error (default to 10 if not provided)
 *   retryInterval: 500, //The interval in millies between get connection retry attempts (defaults to 250 millies if not provided)
 *   runValidationSQL: true, //True to ensure the connection returned is valid by running a test validation SQL (defaults to true)
 *   usePingValidation: true, //If runValidationSQL, this flag will define if validation should first attempt to use connection.ping instead of running a SQL
 *   validationSQL: 'SELECT 1 FROM DUAL', //The test SQL to invoke before returning a connection to validate the connection is open (defaults to 'SELECT 1 FROM DUAL')
 *   //any other oracledb pool attributes
 * }).then(function onPoolCreated(pool) {
 *   pool.getConnection(function onConnection(poolError, connection) {
 *     //continue flow (connection, if provided, has been tested to ensure it is valid)
 *   });
 * });
 * ```
 */
Pool.prototype.getConnection = function (callback) {
    const self = this;

    const onWrapperConnectionCreated = function (error, connection) {
        /*istanbul ignore else*/
        if ((!error) && connection) {
            self.setupEvents(connection);
        }

        callback(error, connection);
    };

    asyncLib.retry({
        times: self.poolAttributes.retryCount,
        interval: self.poolAttributes.retryInterval
    }, function attemptGetConnection(asyncCallback) {
        self.baseGetConnection(function onConnection(error, connection) {
            if (error) {
                debug('Unable to get pooled connection, ', error.stack);
                asyncCallback(error);
            } else if (self.poolAttributes.runValidationSQL && self.poolAttributes.validationSQL) {
                const onPing = function (testError) {
                    if (testError) {
                        debug('Pooled connection validation failed, ', testError.stack);

                        connection.release(function onConnectionRelease(releaseError) {
                            if (releaseError) {
                                debug('Unable to release connection, ', releaseError.stack);
                            }

                            asyncCallback(testError);
                        });
                    } else {
                        asyncCallback(error, connection);
                    }
                };

                if (self.poolAttributes.usePingValidation && connection.ping && typeof connection.ping === 'function') {
                    connection.ping(onPing);
                } else {
                    connection.execute(self.poolAttributes.validationSQL, onPing);
                }
            } else {
                asyncCallback(error, connection);
            }
        });
    }, Connection.wrapOnConnection(onWrapperConnectionCreated));
};
//jscs:enable jsDoc
/*eslint-enable valid-jsdoc*/

//add promise support
Pool.prototype.getConnection = promiseHelper.promisify(Pool.prototype.getConnection);

/*eslint-disable valid-jsdoc*/
//jscs:disable jsDoc
/**
 * This function invokes the provided action (function) with a valid connection object and a callback.

 * The action can use the provided connection to run any connection operation/s (execute/query/transaction/...) and after finishing it
 * must call the callback with an error (if any) and result.

 * For promise support, the action can simply return a promise instead of calling the provided callback.

 * The pool will ensure the connection is released properly and only afterwards will call the provided callback with the action error/result.

 * This function basically will remove the need of caller code to get and release a connection and focus on the actual database operation logic.

 * For extended promise support, the action provided can return a promise instead of calling the provided callback (see examples).
 *
 * @function
 * @memberof! Pool
 * @public
 * @param {ConnectionAction} action - An action requested by the pool to be invoked.
 * @param {Object} [options] - Optional runtime options
 * @param {Boolean} [options.ignoreReleaseErrors=false] - If true, errors during connection.release() invoked by the pool will be ignored
 * @param {Object} [options.releaseOptions={force: false}] - The connection.release options (see connection.release for more info)
 * @param {Boolean} [options.releaseOptions.force=false] - If force=true the connection.break will be called before trying to release to ensure all running activities are aborted
 * @param {AsyncCallback} [callback] - Invoked with an error or the result of the action after the connection was released by the pool
 * @returns {Promise} In case of no callback provided in input, this function will return a promise
 * @example
 * ```js
 * pool.run(function (connection, callback) {
 *   //run some query and the output will be available in the 'run' callback
 *   connection.query('SELECT department_id, department_name FROM departments WHERE manager_id < :id', [110], callback);
 * }, function onActionDone(error, result) {
 *   //do something with the result/error
 * });
 *
 * pool.run(function (connection, callback) {
 *   //run some database operations in a transaction
 *   connection.transaction([
 *     function firstAction(callback) {
 *       connection.insert(...., callback);
 *     },
 *     function secondAction(callback) {
 *       connection.update(...., callback);
 *     }
 *   ], {
 *     sequence: true
 *   }, callback); //at end of transaction, call the pool provided callback
 * }, {
 *   ignoreReleaseErrors: false //enable/disable ignoring any release error (default not to ignore)
 * }, function onActionDone(error, result) {
 *   //do something with the result/error
 * });
 *
 * //another example but with promise support
 * pool.run(function (connection, callback) {
 *   //run some query and the output will be available in the 'run' promise 'then'
 *   connection.query('SELECT department_id, department_name FROM departments WHERE manager_id < :id', [110], callback);
 * }).then(function onActionDone(result) {
 *   //do something with the result
 * });
 *
 * //extended promise support (action is returning a promise instead of using the callback)
 * pool.run(function (connection) {
 *   //run some query and the output will be available in the 'run' promise 'then'
 *   return connection.query('SELECT department_id, department_name FROM departments WHERE manager_id < :id', [110]); //no need for a callback, instead return a promise
 * }).then(function onActionDone(result) {
 *   //do something with the result
 * });
 * ```
 */
Pool.prototype.run = function (action, options, callback) {
    const self = this;

    if ((!callback) && (typeof options === 'function')) {
        callback = options;
        options = null;
    }

    if (action && (typeof action === 'function')) {
        options = options || {};
        const releaseOptions = options.releaseOptions || {};

        const simpleOracleDB = require('./simple-oracledb');
        const actionRunner = simpleOracleDB.createOnConnectionCallback(action, options, releaseOptions, callback);
        self.getConnection(actionRunner);
    } else {
        callback(new Error('Illegal input provided.'));
    }
};
//jscs:enable jsDoc
/*eslint-enable valid-jsdoc*/

//add promise support
Pool.prototype.run = promiseHelper.promisify(Pool.prototype.run, {
    callbackMinIndex: 1
});

/*eslint-disable valid-jsdoc*/
//jscs:disable jsDoc
/**
 * This function invokes the requested queries in parallel (limiting it based on the amount of node.js thread pool size).

 * In order for the queries to run in parallel, multiple connections will be used so use this with caution.
 *
 * @function
 * @memberof! Pool
 * @public
 * @param {QuerySpec[]} querySpec - Array of query spec objects
 * @param {Object} [options] - Optional runtime options
 * @param {Number} [options.limit] - The max connections to be used in parallel (if not provided, it will be calcaulated based on the current node.js thread pool size)
 * @param {AsyncCallback} [callback] - Invoked with an error or an array of query results
 * @returns {Promise} In case of no callback provided in input, this function will return a promise
 * @example
 * ```js
 * pool.parallelQuery([
 *   {
 *     sql: 'SELECT department_id, department_name FROM departments WHERE manager_id = :id',
 *     bindParams: [100],
 *     options: {
 *       //any options here
 *     }
 *   },
 *   {
 *     sql: 'SELECT * FROM employees WHERE manager_id = :id',
 *     bindParams: {
 *       id: 100
 *     }
 *   }
 * ], function onQueriesDone(error, results) {
 *   //do something with the result/error
 *   const query1Results = results[0];
 *   const query2Results = results[1];
 * });
 *
 * //another example but with promise support
 * pool.parallelQuery([
 *   {
 *     sql: 'SELECT department_id, department_name FROM departments WHERE manager_id = :id',
 *     bindParams: [100],
 *     options: {
 *       //any options here
 *     }
 *   },
 *   {
 *     sql: 'SELECT * FROM employees WHERE manager_id = :id',
 *     bindParams: {
 *       id: 100
 *     }
 *   }
 * ]).then(function onQueriesDone(results) {
 *   //do something with the result
 *   const query1Results = results[0];
 *   const query2Results = results[1];
 * });
 * ```
 */
Pool.prototype.parallelQuery = function (querySpec, options, callback) {
    const self = this;

    if ((!callback) && (typeof options === 'function')) {
        callback = options;
        options = null;
    }

    if ((!querySpec) || (!querySpec.length)) {
        callback(new Error('Query spec not provided.'));
    } else {
        //get limit
        let limit = constants.parallelLimit;
        if (options && options.limit) {
            limit = options.limit;
        }

        const createQuery = function (spec) {
            return function run(asyncCallback) {
                self.run(function query(connection, queryCallback) {
                    connection.query(spec.sql, spec.bindParams, spec.options, queryCallback);
                }, asyncCallback);
            };
        };

        const functions = [];
        for (let index = 0; index < querySpec.length; index++) {
            functions.push(createQuery(querySpec[index]));
        }

        asyncLib.parallelLimit(functions, limit, callback);
    }
};
//jscs:enable jsDoc
/*eslint-enable valid-jsdoc*/

//add promise support
Pool.prototype.parallelQuery = promiseHelper.promisify(Pool.prototype.parallelQuery);

/*eslint-disable valid-jsdoc*/
//jscs:disable jsDoc
/**
 * This function modifies the existing pool.terminate function by enabling the input
 * callback to be an optional parameter.

 * Since there is no real way to release the pool that fails to be terminated, all that you can do in the callback
 * is just log the error and continue.

 * Therefore this function allows you to ignore the need to pass a callback and makes it as an optional parameter.

 * The pool.terminate also has an alias pool.close for consistent close function naming to all relevant objects.
 *
 * @function
 * @memberof! Pool
 * @public
 * @param {function} [callback] - An optional terminate callback function (see oracledb docs)
 * @returns {Promise} In case of no callback provided in input and promise is supported, this function will return a promise
 * @example
 * ```js
 * pool.terminate(); //no callback needed
 *
 * //still possible to call with a terminate callback function
 * pool.terminate(function onTerminate(error) {
 *   if (error) {
 *     //now what?
 *   }
 * });
 *
 * //can also use close
 * pool.close();
 * ```
 */
Pool.prototype.terminate = function (callback) {
    const self = this;

    self.baseTerminate(function onPoolTerminate(error) {
        self.emit('release');

        callback(error);
    });
};
//jscs:enable jsDoc
/*eslint-enable valid-jsdoc*/

//add promise support
Pool.prototype.terminate = promiseHelper.promisify(Pool.prototype.terminate, {
    defaultCallback: true
});

/**
 * Alias for pool.terminate, see pool.terminate for more info.
 *
 * @function
 * @memberof! Pool
 * @public
 * @param {function} [callback] - An optional terminate callback function (see oracledb docs)
 * @returns {Promise} In case of no callback provided in input and promise is supported, this function will return a promise
 */
Pool.prototype.close = Pool.prototype.terminate;

/**
 * Sets the pool attribute defaults.
 *
 * @function
 * @memberof! Pool
 * @private
 * @param {Object} [poolAttributes] - The connection pool attributes object
 * @returns {Object} The modified pool attributes to use for the newly created pool
 * @example
 * ```js
 * //set defaults
 * pool.poolAttributes = setupPoolAttributes(poolAttributes);
 * ```
 */
function setupPoolAttributes(poolAttributes) {
    poolAttributes = poolAttributes || {};

    //set defaults
    poolAttributes.retryCount = Math.max(poolAttributes.retryCount || 10, 1);
    poolAttributes.retryInterval = poolAttributes.retryInterval || 250;
    if (poolAttributes.runValidationSQL === undefined) {
        poolAttributes.runValidationSQL = true;
    }
    if (poolAttributes.usePingValidation === undefined) {
        poolAttributes.usePingValidation = true;
    }
    poolAttributes.validationSQL = poolAttributes.validationSQL || 'SELECT 1 FROM DUAL';

    return poolAttributes;
}

module.exports = {
    /**
     * Extends the provided oracledb pool instance.
     *
     * @function
     * @memberof! Pool
     * @public
     * @param {Object} pool - The oracledb pool instance
     * @param {Object} [poolAttributes] - The connection pool attributes object
     * @param {Number} [poolAttributes.retryCount=10] - The max amount of retries to get a connection from the pool in case of any error
     * @param {Number} [poolAttributes.retryInterval=250] - The interval in millies between get connection retry attempts
     * @param {Boolean} [poolAttributes.runValidationSQL=true] - True to ensure the connection returned is valid by running a test ping or validation SQL
     * @param {Boolean} [poolAttributes.usePingValidation=true] - If runValidationSQL, this flag will define if validation should first attempt to use connection.ping instead of running a SQL
     * @param {String} [poolAttributes.validationSQL=SELECT 1 FROM DUAL] - The test SQL to invoke before returning a connection to validate the connection is open
     */
    extend: function extend(pool, poolAttributes) {
        if (pool && (!pool.simplified)) {
            //set defaults
            pool.poolAttributes = setupPoolAttributes(poolAttributes);

            let properties = Object.keys(Pool.prototype);

            properties.forEach(function addProperty(property) {
                if (typeof pool[property] === 'function') {
                    pool['base' + property.charAt(0).toUpperCase() + property.slice(1)] = pool[property];
                }

                pool[property] = Pool.prototype[property];
            });

            const extendedCapabilities = extensions.get('pool');
            properties = Object.keys(extendedCapabilities);

            properties.forEach(function addProperty(property) {
                if (!pool[property]) {
                    pool[property] = extendedCapabilities[property];
                }
            });

            emitter(pool);

            pool.diagnosticInfo = pool.diagnosticInfo || {};
            pool.diagnosticInfo.id = poolIDCounter;
            poolIDCounter++;
        }
    }
};


text:
<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;

/* @var $this yii\web\View */
/* @var $model frontend\modules\vendor\models\ProductsSearch */
/* @var $form yii\widgets\ActiveForm */
?>

    <?php $form = ActiveForm::begin([
        'action' => ['index'],
        'method' => 'get',
    ]); ?>

    <?= $form->field($model, 'productId') ?>

    <?= $form->field($model, 'productCode') ?>

    <?= $form->field($model, 'vendorId') ?>

    <?= $form->field($model, 'branchId') ?>

    <?= $form->field($model, 'productName') ?>

    <?php // echo $form->field($model, 'categoryId') ?>

    <?php // echo $form->field($model, 'description') ?>

    <?php // echo $form->field($model, 'productStatus') ?>

    <?php // echo $form->field($model, 'cashOnDeliveryStatus') ?>

    <?php // echo $form->field($model, 'CashOnDeliveryPrice') ?>

    <?php // echo $form->field($model, 'productColor') ?>

    <?php // echo $form->field($model, 'sareeFabric') ?>

    <?php // echo $form->field($model, 'sareeType') ?>

    <?php // echo $form->field($model, 'sareeWork') ?>

    <?php // echo $form->field($model, 'sareeLength') ?>

    <?php // echo $form->field($model, 'blouseAvailable') ?>

    <?php // echo $form->field($model, 'blouseColor') ?>

    <?php // echo $form->field($model, 'blouseWork') ?>

    <?php // echo $form->field($model, 'blouseFabric') ?>

    <?php // echo $form->field($model, 'blouseSize') ?>

    <?php // echo $form->field($model, 'pettiCoat') ?>

    <?php // echo $form->field($model, 'occation') ?>

    <?php // echo $form->field($model, 'WashCare') ?>

    <?php // echo $form->field($model, 'createdBy') ?>

    <?php // echo $form->field($model, 'updatedBy') ?>

    <?php // echo $form->field($model, 'createdDate') ?>

    <?php // echo $form->field($model, 'updatedDate') ?>

    <?php // echo $form->field($model, 'status') ?>

        <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
        <?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?>

    <?php ActiveForm::end(); ?>

redpajama_set_name: RedPajamaGithub


text:
import template from './view-bbi-opportunity.html';
import app from '~/app';
import _ from 'lodash';
import '~/services/storage';

	app.directive('viewBbiOpportunity', ["IStorage","$location", function (storage,$location) {
		return {
			restrict: 'E',
			template: template,
			replace: true,
			transclude: false,
			scope: {
				document: '=ngModel',
				locale	: '=',
				loading:"=?",
									user:"=?",
				header:"=?"
			},
			link: function($scope) {
								//
								if(typeof $scope.header==='undefined') $scope.header=true;

                var killWatchContact = $scope.$watch("document.contact", function()
                {
                    if($scope.document )
                    $scope.contact = angular.fromJson(angular.toJson($scope.document.contact));

                    if($scope.contact)

												if($scope.contact)
		                        $scope.loadReferences($scope.contact).then(function(data){
		                            $scope.contact = data[0];

																if(data[0] && data[0].contactOrganization)

																		$scope.loadReferences(data[0].contactOrganization).then(function(d){

																				$scope.contactOrg = d[0];
																				killWatchContact();
																		});
																else killWatchContact();
		                        });
                });
								//====================
								//
								//====================
								$scope.isAdmin = function() {
									if($scope.user)
										 return !!_.intersection($scope.user.roles, ["Administrator","BbiAdministrator"]).length;
								};
								//====================
								//
								//====================
								$scope.isReview = function() {
										 return !!($location.url().indexOf('/view')>-1);
								};
                //====================
                //
                //====================
                var killWatchPriCon = $scope.$watch("document.primaryOrganization", function()
                {
                    if(!$scope.document || ($scope.document && !$scope.document.primaryOrganization)) return;

                    $scope.primaryOrganization = angular.fromJson(angular.toJson($scope.document.primaryOrganization));
                    if($scope.primaryOrganization)
                        $scope.loadReferences($scope.primaryOrganization).then(function(data){
                            $scope.primaryOrganization = data[0];
														if($scope.primaryOrganization.organization)
														$scope.loadReferences($scope.primaryOrganization.organization).then(function(orgData){
																Object.assign($scope.primaryOrganization,orgData[0]);
														});
														killWatchPriCon();
                        });
                });

								//====================
                //
                //====================
                var killWatchOrgs = $scope.$watch("document.organizations", function()
                {
                    if(!$scope.document || ($scope.document && !$scope.document.organizations))return;

										$scope.organizations  = angular.fromJson(angular.toJson($scope.document.organizations));

                    if($scope.organizations && Array.isArray($scope.organizations ))
											for(var i =0 ; i< $scope.organizations.length;i++){
												$scope.loadReferences($scope.organizations,i).then(function(data){ //jshint ignore:line
														Object.assign($scope.organizations[data[1]],data[0]);
   													if($scope.organizations[data[1]].organization)
														$scope.loadReferences($scope.organizations[data[1]].organization).then(function(orgData){
																Object.assign($scope.organizations[data[1]],orgData[0]);
														});
												});
											}
										killWatchOrgs();
                });
								//====================
								//
								//====================
								$scope.getLogo = function(org) {
										if(!org) org = $scope.primaryOrganization;
									  if( !org) return false;

										return _.find(org.relevantDocuments,{name:'logo'});
								};
                //====================
                //
                //====================
                $scope.loadReferences = function(ref,index) {
									if(!ref)return;
									if(Number.isInteger(index) && Array.isArray(ref)) ref=ref[index];
                   return storage.documents.get(ref.identifier, { cache : true})
                        .then(function(data){
													 ref=[];
                            ref[0] = data.data;
														ref[0].header.state='public';
														ref[1] = index;
                            return ref;
                        })
                        .catch(function(error, code){
                            if (error.status == 404) {

                            return storage.drafts.get(ref.identifier, { cache : true})
                                    .then(function(data){
																			ref=[];
					                             ref[0] = data.data;
																			 ref[0].header.state='draft';
					 														ref[1] = index;
                                        return ref;
                                    })
                                    .catch(function(error){
                                        return { error  : error, errorCode : code};
                                    });
                            }
                            else{
                                return { error  : error, errorCode : code};
                            }
                        });
                };
			}
		};
	}]);


text:
using System.Windows.Controls;

namespace Plainion.GraphViz.Modules.CodeInspection.CallTree
{
    partial class CallTreeView : UserControl
    {
        public CallTreeView( CallTreeViewModel model )
        {
            InitializeComponent();

            DataContext = model;
        }
    }
}


text:
"""Top-level package for ipfromwebpage."""
from .ipfromwebpage import *


text:
<?php

namespace OverworldGlitches\DarkWorld;

use ALttP\Item;
use ALttP\World;
use TestCase;

/**
 * @group OverworldGlitches
 */
class SouthTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        $this->world = World::factory('standard', ['difficulty' => 'test_rules', 'logic' => 'OverworldGlitches']);
        $this->addCollected(['RescueZelda']);
        $this->collected->setChecksForWorld($this->world->id);
    }

    public function tearDown(): void
    {
        parent::tearDown();
        unset($this->world);
    }

    /**
     * @param string $location
     * @param bool $access
     * @param array $items
     * @param array $except
     *
     * @dataProvider accessPool
     */
    public function testLocation(string $location, bool $access, array $items, array $except = [])
    {
        if (count($except)) {
            $this->collected = $this->allItemsExcept($except);
        }

        $this->addCollected($items);

        $this->assertEquals($access, $this->world->getLocation($location)
            ->canAccess($this->collected));
    }

    public function accessPool()
    {
        return [
            ["Hype Cave - Top", false, []],
            ["Hype Cave - Top", false, [], ['MoonPearl']],
            ["Hype Cave - Top", true, ['MoonPearl', 'PegasusBoots']],

            ["Hype Cave - Middle Right", false, []],
            ["Hype Cave - Middle Right", false, [], ['MoonPearl']],
            ["Hype Cave - Middle Right", true, ['MoonPearl', 'PegasusBoots']],

            ["Hype Cave - Middle Left", false, []],
            ["Hype Cave - Middle Left", false, [], ['MoonPearl']],
            ["Hype Cave - Middle Left", true, ['MoonPearl', 'PegasusBoots']],

            ["Hype Cave - Bottom", false, []],
            ["Hype Cave - Bottom", false, [], ['MoonPearl']],
            ["Hype Cave - Bottom", true, ['MoonPearl', 'PegasusBoots']],

            ["Hype Cave - NPC", false, []],
            ["Hype Cave - NPC", false, [], ['MoonPearl']],
            ["Hype Cave - NPC", true, ['MoonPearl', 'PegasusBoots']],

            ["Stumpy", false, []],
            ["Stumpy", false, [], ['MoonPearl']],
            ["Stumpy", true, ['MoonPearl', 'PegasusBoots']],

            ["Digging Game", false, []],
            ["Digging Game", false, [], ['MoonPearl']],
            ["Digging Game", true, ['MoonPearl', 'PegasusBoots']],
        ];
    }
}


text:
define(['../internals/baseClone', '../internals/baseCreateCallback'], function(baseClone, baseCreateCallback) {

  /**
   * Creates a deep clone of `value`. If a callback is provided it will be
   * executed to produce the cloned values. If the callback returns `undefined`
   * cloning will be handled by the method instead. The callback is bound to
   * `thisArg` and invoked with two argument; (value, index|key).
   *
   * Note: This method is loosely based on the structured clone algorithm. Functions
   * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
   * objects created by constructors other than `Object` are cloned to plain `Object` objects.
   * See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm)
   * for more details.
   *
   * @static
   * @memberOf _
   * @category Objects
   * @param {*} value The value to deep clone.
   * @param {Function} [callback] The function to customize cloning values.
   * @param {*} [thisArg] The `this` binding of `callback`.
   * @returns {*} Returns the deep cloned value.
   * @example
   *
   * var characters = [
   *   { 'name': 'barney', 'age': 36 },
   *   { 'name': 'fred',   'age': 40 }
   * ];
   *
   * var deep = _.cloneDeep(characters);
   * deep[0] === characters[0];
   * // => false
   *
   * var view = {
   *   'label': 'docs',
   *   'node': element
   * };
   *
   * var clone = _.cloneDeep(view, function(value) {
   *   return _.isElement(value) ? value.cloneNode(true) : undefined;
   * });
   *
   * clone.node == view.node;
   * // => false
   */
  function cloneDeep(value, callback, thisArg) {
    callback = typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1);
    return baseClone(value, true, callback);
  }

  return cloneDeep;
});


text:
@implementation FEUser

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.userInfo = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.userID     forKey:@"userID"];
    [aCoder encodeObject:self.username   forKey:@"username"];
    [aCoder encodeObject:self.password   forKey:@"password"];
    [aCoder encodeObject:self.userInfo   forKey:@"userInfo"];
    [aCoder encodeObject:self.updateDate forKey:@"updateDate"];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        self.userID     = [aDecoder decodeObjectForKey:@"userID"];
        self.username   = [aDecoder decodeObjectForKey:@"username"];
        self.password   = [aDecoder decodeObjectForKey:@"password"];
        self.userInfo   = [aDecoder decodeObjectForKey:@"userInfo"];
        self.updateDate = [aDecoder decodeObjectForKey:@"updateDate"];
    }
    return self;
}

@end


text:
*([Issues](https://github.com/sass/sass/issues/2744),
[Changelog](forward-with.changes.md))*

## Table of Contents

* [Background](#background)
* [Summary](#summary)
* [Syntax](#syntax)
* [Semantics](#semantics)

## Background

> This section is non-normative.

In the existing module system each module can only be cofigured once,
the first time it is used. That works well for direct use of modules,
but doesn't allow for "middleware" modules to forward pre-configured,
and re-configurable modules. It is often useful for complex libraries to
provide a "core" module with unopinionated defaults, and then specialized
wrapper modules with more opinionated configurations and additional helpers.
That wrapper package needs to:

1. Set some or all origin-package configurations
2. Allow the user to *also* set some or all origin-package configurations,
   along with new middleware configurations
3. Use the configured origin-package to provide additional members
   based on the fully-configured origin module

Part 3 should be possible in the existing system by writing the `@forward`
rules before the `@use` rules, but parts 1 and 2 are not currently possible
in combination.

This proposal provides a syntax for middleware modules to add configuration
of the root module, without removing that option for end-users.

## Summary

> This section is non-normative.

Sass will add a `with` clause to `@forward`. The `@forward ... with` syntax is
based on the `@use ... with` syntax, but allows the addition of `!default` flags
similar to a [variable declaration][]. Unlike `@use ... with`, unconfigured
origin variables, and variables configured with a `!default` flag, will remain
configurable by any file importing the combined module. For example:

[variable declaration]: ../spec/variables.md#syntax

```scss
// _origin.scss
$hue: 0 !default;
$saturation: 50% !default;
```

```scss
// _middleware.scss
@forward "origin" with (
  $hue: 330 !default, // Can be overridden by importing users.
  $saturation: 70% // Cannot be overridden by importing users.
);
```

```scss
// entrypoint.scss
@use "middleware" with (
  $hue: 120 // override both the origin & middleware !default values
);

// middleware.$hue == 120
// middleware.$saturation == 70%
```

Keyword arguments in the configuration must reference variable names as
defined in the forwarded module, regardless of any concurent `as` clause:

```scss
// _origin.scss
$hue: 0 !default;
$color-hex: #ccc !default;
```

```scss
// _middleware.scss
@forward "origin" as color-* with (
  $hue: 330, // the color-* prefix is not referenced in configuration
  $color-hex: #966
);
```

```scss
// entrypoint.scss
@use "middleware" as m;
// m.$color-hue == 330
// m.$color-hex == #966
```

A `@forward` rule configuration is applied to the source module even if the
forwarding module acts as an entrypoint:

```scss
// _origin.scss
$hue: 0 !default;
```

```scss
// entrypoint.scss
@forward "origin" with (
  $hue: 330 !default
);

@use "origin"; // origin.$hue == 330
```

Multiple configurations can be chained in a single cascading "thread" that
contains zero or more `@forward` rules, and zero or one terminal `@use` rule.
Variables remain open to configuration in the chain as long as every mention
includes the `!default` flag. Multiple threads configuring a single module will
cause an error, even if they originate in the same file.

## Syntax

The new `WithClause` extends `@forward` to the follow grammar:

<x><pre>
**ForwardRule**     ::= '@forward' QuotedString AsClause? (ShowClause | HideClause)?  WithClause?
**WithClause**      ::= 'with' '('
                      KeywordArgument (',' KeywordArgument)\* ','?
                    ')'
**ForwardWithArgument** ::= '$' Identifier ':' Expression '!default'?
</pre></x>

## Semantics

The `@forward ... with` semantics builds on the existing proposal for
[Executing Files][], and should be understood as modifying and expanding upon
the existing execution process rather than being a comprehensive replacement.

[Executing Files]: ../accepted/module-system.md#executing-files

Given a source file `file`, a configuration `config`, and an import context
`import`:

* Let `module` be an empty module with the same URL as `file`.

* Let `uses` be an empty map from `@use` rules to [modules][].

* When a `@use` rule `rule` is encountered:

  * If `rule` has a namespace that's the same as another `@use` rule's namespace
    in `file`, throw an error.

  * Let `rule-config` be the empty configuration.

  * If `rule` has a `WithClause`:

    * For each `KeywordArgument` `argument` in this clause:

      * Let `value` be the result of evaluating `argument`'s expression.

      * Add a variable to `rule-config` with the same name as `argument`'s
        identifier and with `value` as its value.

  * Let `module` be the result of [loading][] the module with `rule`'s URL
    and `rule-config`.

  * If `rule` has a `WithClause` that contains any variables that aren't part of
    `module`'s public API or that weren't declared with a `!default` flag in
    `module`, throw an error.

  * Associate `rule` with `module` in `uses`.

* When a `@forward` rule `rule` is encountered:

  * If `rule` has an `AsClause` with identifier `prefix`:

    * Let `rule-config` be an empty configuration.

    * For each variable `variable` in `config`:

      * If `variable`'s name begins with `prefix`:

        * Let `suffix` be the portion of `variable`'s name after `prefix`.

        * Add a variable to `rule-config` with the name `suffix` and with the
          same value as `variable`.

  * Otherwise, let `rule-config` be `config`.

  * If `rule` has a `WithClause`:

    * For each `ForwardWithArgument` `argument` in this clause:

      * If `argument` has a `!default` flag and a variable exists in
        `rule-config` with the same name as `argument`'s identifier, do nothing.

      * Otherwise, let `value` be the result of evaluating `argument`'s
        expression.

      * Add a variable to `rule-config` with the same name as `argument`'s
        identifier, and with `value` as its value.

  * Let `forwarded` be the result of [loading][] the module with `rule`'s URL
    and `rule-config`.

  * If `rule` has a `WithClause` that contains any variables that aren't part of
    `forwarded`'s public API or that weren't declared with a `!default` flag in
    `forwarded`, throw an error.

  * [Forward `forwarded`][forwarding] with `file` through `module`.

> From this point on, the logic remains unchanged.

[modules]: ../accepted/module-system.md#module
[loading]: ../accepted/module-system.md#loading-modules
[forwarding]: ../accepted/module-system.md#forwarding-modules


text:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TupleSections #-}

-- | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-lifecycleconfig-rule-noncurrentversiontransition.html

module Stratosphere.ResourceProperties.S3BucketNoncurrentVersionTransition where

import Stratosphere.ResourceImports

-- | Full data type definition for S3BucketNoncurrentVersionTransition. See
-- 's3BucketNoncurrentVersionTransition' for a more convenient constructor.
data S3BucketNoncurrentVersionTransition =
  S3BucketNoncurrentVersionTransition
  { _s3BucketNoncurrentVersionTransitionStorageClass :: Val Text
  , _s3BucketNoncurrentVersionTransitionTransitionInDays :: Val Integer
  } deriving (Show, Eq)

instance ToJSON S3BucketNoncurrentVersionTransition where
  toJSON S3BucketNoncurrentVersionTransition{..} =
    object $
    catMaybes
    [ (Just . ("StorageClass",) . toJSON) _s3BucketNoncurrentVersionTransitionStorageClass
    , (Just . ("TransitionInDays",) . toJSON) _s3BucketNoncurrentVersionTransitionTransitionInDays
    ]

-- | Constructor for 'S3BucketNoncurrentVersionTransition' containing required
-- fields as arguments.
s3BucketNoncurrentVersionTransition
  :: Val Text -- ^ 'sbnvtStorageClass'
  -> Val Integer -- ^ 'sbnvtTransitionInDays'
  -> S3BucketNoncurrentVersionTransition
s3BucketNoncurrentVersionTransition storageClassarg transitionInDaysarg =
  S3BucketNoncurrentVersionTransition
  { _s3BucketNoncurrentVersionTransitionStorageClass = storageClassarg
  , _s3BucketNoncurrentVersionTransitionTransitionInDays = transitionInDaysarg
  }

-- | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-lifecycleconfig-rule-noncurrentversiontransition.html#cfn-s3-bucket-lifecycleconfig-rule-noncurrentversiontransition-storageclass
sbnvtStorageClass :: Lens' S3BucketNoncurrentVersionTransition (Val Text)
sbnvtStorageClass = lens _s3BucketNoncurrentVersionTransitionStorageClass (\s a -> s { _s3BucketNoncurrentVersionTransitionStorageClass = a })

-- | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-lifecycleconfig-rule-noncurrentversiontransition.html#cfn-s3-bucket-lifecycleconfig-rule-noncurrentversiontransition-transitionindays
sbnvtTransitionInDays :: Lens' S3BucketNoncurrentVersionTransition (Val Integer)
sbnvtTransitionInDays = lens _s3BucketNoncurrentVersionTransitionTransitionInDays (\s a -> s { _s3BucketNoncurrentVersionTransitionTransitionInDays = a })


text:
package io.jooby.quartz;

import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;

import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.quartz.CalendarIntervalTrigger;
import org.quartz.CronTrigger;
import org.quartz.DailyTimeIntervalTrigger;
import org.quartz.InterruptableJob;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;

import edu.umd.cs.findbugs.annotations.Nullable;
import io.jooby.Context;
import io.jooby.Jooby;
import io.jooby.StatusCode;
import io.jooby.internal.quartz.JobGenerator;

/**
 * REST API over {@link Scheduler} operations.
 *
 * @author edgar
 * @since 2.5.1
 */
public class QuartzApp extends Jooby {

  private Scheduler scheduler;

  {
    get(
        "/",
        ctx -> {
          Scheduler scheduler = getScheduler();
          List<JobKey> jobKeys = new ArrayList<>();
          for (String group : scheduler.getJobGroupNames()) {
            jobKeys.addAll(scheduler.getJobKeys(GroupMatcher.groupEquals(group)));
          }
          return jobKeys;
        });

    get(
        "/{group}/{name}",
        ctx -> {
          Scheduler scheduler = getScheduler();
          JobKey jobKey = jobKey(ctx);
          return toMap(
              scheduler.getJobDetail(jobKey), scheduler.getTriggersOfJob(jobKey), zoneId(ctx));
        });

    get(
        "/{group}/{name}/trigger",
        ctx -> {
          Scheduler scheduler = getScheduler();
          JobKey jobKey = jobKey(ctx);
          if (!isJobRunning(scheduler, jobKey)) {
            scheduler.triggerJob(jobKey, new JobDataMap(ctx.queryMap()));
          }
          return toMap(
              scheduler.getJobDetail(jobKey), scheduler.getTriggersOfJob(jobKey), zoneId(ctx));
        });

    get(
        "/{group}/{name}/interrupt",
        ctx -> {
          Scheduler scheduler = getScheduler();
          JobKey jobKey = jobKey(ctx);
          for (JobExecutionContext jec : scheduler.getCurrentlyExecutingJobs()) {
            JobKey currentKey = jec.getJobDetail().getKey();
            if (currentKey.equals(jobKey)) {
              if (jec.getJobInstance() instanceof InterruptableJob) {
                ((InterruptableJob) jec.getJobInstance()).interrupt();
              }
            }
          }

          return toMap(
              scheduler.getJobDetail(jobKey), scheduler.getTriggersOfJob(jobKey), zoneId(ctx));
        });

    get(
        "/{group}/{name}/pause",
        ctx -> {
          Scheduler scheduler = getScheduler();
          JobKey jobKey = jobKey(ctx);
          scheduler.pauseJob(jobKey);
          return toMap(
              scheduler.getJobDetail(jobKey), scheduler.getTriggersOfJob(jobKey), zoneId(ctx));
        });

    get(
        "/{group}/{name}/resume",
        ctx -> {
          Scheduler scheduler = getScheduler();
          JobKey jobKey = jobKey(ctx);
          scheduler.resumeJob(jobKey);
          return toMap(
              scheduler.getJobDetail(jobKey), scheduler.getTriggersOfJob(jobKey), zoneId(ctx));
        });

    get(
        "/{group}/{name}/reschedule",
        ctx -> {
          Scheduler scheduler = getScheduler();
          String value = ctx.query("trigger").value();
          JobKey jobKey = jobKey(ctx);
          Trigger trigger = JobGenerator.newTrigger(getConfig(), value, jobKey);
          scheduler.rescheduleJob(trigger.getKey(), trigger);
          return toMap(
              scheduler.getJobDetail(jobKey), scheduler.getTriggersOfJob(jobKey), zoneId(ctx));
        });

    /** Delete a job and their associated trigger(s). */
    delete(
        "/{group}/{name}",
        ctx -> {
          Scheduler scheduler = getScheduler();
          JobKey jobKey = jobKey(ctx);
          scheduler.deleteJob(jobKey);
          return ctx.send(StatusCode.NO_CONTENT);
        });
  }

  private ZoneId zoneId(Context ctx) {
    return ctx.query("zoneId").toOptional(ZoneId.class).orElse(ZoneId.of("UTC"));
  }

  private JobKey jobKey(Context ctx) {
    return JobKey.jobKey(ctx.path("name").value(), ctx.path("group").value());
  }

  private TriggerKey triggerKey(Context ctx) {
    return TriggerKey.triggerKey(ctx.path("name").value(), ctx.path("group").value());
  }

  private Map<String, Object> toMap(
      JobDetail detail, List<? extends Trigger> triggers, ZoneId zoneId) throws SchedulerException {
    Map<String, Object> json = new LinkedHashMap<>();
    json.put("key", detail.getKey().toString());
    Optional.ofNullable(detail.getDescription()).ifPresent(value -> json.put("description", value));

    json.put("stoppable", InterruptableJob.class.isAssignableFrom(detail.getJobClass()));
    json.put("concurrentExecutionDisallowed", detail.isConcurrentExectionDisallowed());
    json.put("durable", detail.isDurable());
    json.put("persistJobDataAfterExecution", detail.isPersistJobDataAfterExecution());
    json.put("requestsRecovery", detail.requestsRecovery());
    json.put("triggers", toJson(triggers, zoneId));
    json.put("jobDataMap", detail.getJobDataMap());
    return json;
  }

  private List<Map<String, Object>> toJson(List<? extends Trigger> triggers, ZoneId zoneId)
      throws SchedulerException {
    List<Map<String, Object>> result = new ArrayList<>();
    for (Trigger trigger : triggers) {
      result.add(toJson(trigger, zoneId));
    }
    return result;
  }

  private Map<String, Object> toJson(Trigger trigger, ZoneId zoneId) throws SchedulerException {
    Scheduler scheduler = getScheduler();
    Trigger.TriggerState state = scheduler.getTriggerState(trigger.getKey());

    Map<String, Object> json = new LinkedHashMap<>();
    json.put("key", trigger.getKey().toString());

    json.put("state", state);

    json.put("priority", trigger.getPriority());

    Optional.ofNullable(trigger.getCalendarName())
        .ifPresent(value -> json.put("calendarName", value));
    Optional.ofNullable(trigger.getDescription())
        .ifPresent(value -> json.put("description", value));

    json.put("zoneId", zoneId);

    json.put("startTime", format(trigger.getStartTime(), zoneId));
    json.put("endTime", format(trigger.getEndTime(), zoneId));
    json.put("finalFireTime", format(trigger.getFinalFireTime(), zoneId));
    json.put("nextFireTime", format(trigger.getNextFireTime(), zoneId));
    json.put("previousFireTime", format(trigger.getPreviousFireTime(), zoneId));

    json.put("misfireInstruction", trigger.getMisfireInstruction());

    json.put("mayFireAgain", trigger.mayFireAgain());
    if (trigger instanceof CronTrigger) {
      json.put("cron", ((CronTrigger) trigger).getCronExpression());
    } else if (trigger instanceof SimpleTrigger) {
      json.put("repeatCount", ((SimpleTrigger) trigger).getRepeatCount());
      json.put("repeatInterval", ((SimpleTrigger) trigger).getRepeatInterval());
    } else if (trigger instanceof CalendarIntervalTrigger) {
      json.put("repeatInterval", ((CalendarIntervalTrigger) trigger).getRepeatInterval());
      json.put("repeatIntervalUnit", ((CalendarIntervalTrigger) trigger).getRepeatIntervalUnit());
    } else if (trigger instanceof DailyTimeIntervalTrigger) {
      json.put("repeatInterval", ((DailyTimeIntervalTrigger) trigger).getRepeatInterval());
      json.put("repeatIntervalUnit", ((DailyTimeIntervalTrigger) trigger).getRepeatIntervalUnit());
    }

    json.put("jobDataMap", trigger.getJobDataMap());

    return json;
  }

  private Object format(Date dateTime, ZoneId zoneId) {
    return dateTime == null
        ? null
        : ISO_OFFSET_DATE_TIME.withZone(zoneId).format(dateTime.toInstant());
  }

  private boolean isJobRunning(final Scheduler scheduler, final JobKey job)
      throws SchedulerException {
    return runningJob(scheduler, job).isPresent();
  }

  private Optional<JobExecutionContext> runningJob(final Scheduler scheduler, final JobKey job)
      throws SchedulerException {
    List<JobExecutionContext> jobs = scheduler.getCurrentlyExecutingJobs();
    return jobs.stream().filter(it -> it.getJobDetail().getKey().equals(job)).findFirst();
  }

  private Scheduler getScheduler() {
    return scheduler == null ? require(Scheduler.class) : scheduler;
  }

  /**
   * New quartz app.
   *
   * @param scheduler Scheduler to use.
   */
  public QuartzApp(@Nullable Scheduler scheduler) {
    this.scheduler = scheduler;
  }

  /** New quartz app. */
  public QuartzApp() {}
}


text:
[Maven Central]: http://repo2.maven.org/maven2/
[The Big Ball of Mudd]: http://www.laputan.org/mud/
[Wrapper Plugin]: http://bnd.bndtools.org/plugins/wrapper.html
[-buildrepo]: http://bnd.bndtools.org/instructions/buildrepo
[-pom]: http://bnd.bndtools.org/instructions/pom.html
[-connection-settings]: http://bnd.bndtools.org/instructions/connection-settings.html


text:
"""smq goals"""

import numpy as np
from smq.core  import SMQModule
from smq.utils import set_attr_from_dict

################################################################################
# Basic goal class
class Goal(SMQModule):
    """Basic goal, contains a basic goal datum"""
    def __init__(self, conf):
        SMQModule.__init__(self, conf)
        set_attr_from_dict(self, conf["goald"])

        # step counter
        self.cnt = 0
        # goal vector
        self.goal = np.zeros((self.goal_dims_num, 1))

        # some configuration defaults
        if not self.goald.has_key("mins"):
            self.goald["mins"] = -0.7
        if not self.goald.has_key("maxs"):
            self.goald["maxs"] = 0.7

    def step(self, smdict):
        self.sample()
        self.cnt += 1
        return smdict

class JointGoal(Goal):
    """Joint goal is a joint position goal"""
    def __init__(self, conf):
        Goal.__init__(self, conf)
        self.goal = self.sample()

    def sample(self):
        return np.random.uniform(self.goald["mins"], self.goald["maxs"], (self.goal_dims_num, 1))

class PosGoal(Goal):
    """Position goal, sample a goal position for in a given space"""
    def __init__(self, conf):
        Goal.__init__(self, conf)

        # self.goal = self.sample()

    def sample(self):
        # FIXME: configure limits
        if hasattr(self, "goaltype"):
            if self.goaltype == "stdr_sonar":
                ret = np.array([[1.0], [0.55], [0.45]])
            elif self.goaltype == "stdr_pos":
                ret = np.array([[1], [1]])
            # elif self.goaltype == "extero_cart":
            #     # print "%s.sample: self.brain = %s" % (self.__class__.__name__, dir(self.brain))

            #     # now cartesian angular motion is in s_pred, need to change that to proprio
            #     # FIXME: all hardcoded stuff
            #     cond = np.vstack((self.brain.smdict["s_extero"], self.brain.smdict["s_proprio"]))
            #     # print "cond", cond
            #     cond[:self.brain.dim_s_extero] = np.random.uniform(-1.0, 1.0, (1, self.brain.dim_s_extero)).T
            #     # np.random.uniform([0, -1], [1, 1], (1, 2)).T
            #     cond[2:] = np.nan
            #     if self.brain.e2p.fitted:
            #         ret1 = self.brain.e2p.predict(cond).T
            #     else:
            #         ret1 = np.random.uniform(self.goald["mins"], self.goald["maxs"], (self.goal_dims_num, 1))
            #     intero_pos_goal_idx = self.brain.get_sm_index("s_intero", "pos_goal", indexdim = 2)
            #     self.brain.smdict["s_intero"][intero_pos_goal_idx] = cond[:2]
            #     # intero_idx = self.brain.get_sm_index("s_intero", "j_ang_")
            #     # pred_idx = self.brain.get_sm_index("s_pred", "j_ang_vel_pred")
            #     # print "ret", ret, self.smdict["s_intero"][intero_idx]
            #     # print "pred_idx", pred_idx, ret.shape
            #     # self.smdict["s_intero"][intero_idx] = ret.reshape((self.dim_s_motor, 1))
            #     # self.smdict["s_pred"] = ret.reshape((self.dim_s_motor, 1)) #[pred_idx]

            #     # ret = np.random.uniform(self.goald["mins"], self.goald["maxs"], (self.goal_dims_num, 1))
            #     print "%s.sample: goal = %s/%s" % (self.__class__.__name__, ret1.shape, ret1)
            #     # ret = ret1.T
            #     ret = ret1
            #     print "%s.sample: goal = %s/%s" % (self.__class__.__name__, ret.shape, ret)
            else:
                ret = np.random.uniform(0.0, 1.0, (self.goal_dims_num, 1))
        else:
            ret = np.random.uniform(self.goald["mins"], self.goald["maxs"], (self.goal_dims_num, 1))
        return ret

class CntPosGoal(PosGoal):
    """Counting position goal, resample a the goal after fixed number of 'resample_interval'
    time steps"""
    def __init__(self, conf):
        PosGoal.__init__(self, conf)
        self.cnt = 0

        if not hasattr(self, "resample_interval"):
            self.resample_interval = 100

    def step(self, smdict):
        print "%s.step cnt = %d" % (self.__class__.__name__, self.cnt)
        smdict = PosGoal.step(self, smdict)
        if self.cnt % self.resample_interval == 0:
            self.goal = self.sample()

        # FIXME: use decorators to do bookkeeping
        # self.cnt += 1
        return smdict

class AvgErrorPosGoal(PosGoal):
    """Average error position goal, if the average error is below a theshold 'thresh'
    sample a new goal"""
    def __init__(self, conf):
        PosGoal.__init__(self, conf)
        self.avgerror = 0.0
        self.coeff = 0.05
        self.cnt = 0

    def sample(self):
        # compute the average error
        self.avgerror = self.avgerror * (1 - self.coeff) + self.brain.smdict["s_reward"] * self.coeff
        # log average error to sm space
        avgerridx = self.brain.get_sm_index("s_intero", "avgerrorposgoal_avgerror", indexdim = 1)
        self.brain.smdict["s_intero"][avgerridx] = self.avgerror
        # check if threshold exceeded
        if self.cnt == 0 or self.cnt > 100:
            if self.avgerror < self.thresh:
                self.goal = PosGoal.sample(self)
        # FIXME: shouldn't we be logging the goal here?
        print "self.goal = %s" % self.goal
        return self.goal

################################################################################
# Exteroceptive goal class: sample a goal in exteroceptive space and translate that
# via a learned map into proprio space
class ExteroPosGoal(PosGoal):
    """Basic class for an exteroceptive goal. The primary goal exists in exteroceptive space,
    and needs to be mapped into proprioceptive space via the e2p map. Then we pursue the derived
    goal in proprioceptive space
      set proprio base goal dims and parameters
      set extero       goal dims and parameters
      sample: sample a new random (?) extero goal and ask the e2p map to convert that into a proprio goal
      pimp with avgerror for both proprio and extero
      questions:
       - one class or composition of several goals?
       - pack away functions for sampling extero goals based on current state"""
    def __init__(self, conf):
        PosGoal.__init__(self, conf)
        # check if brain is compatible with this goal type
        if not hasattr(self.brain, "e2p"):
            print "%s.__init__: wrong brain, does not seem to have an e2p module, exiting" % (self.__class__.__name__)
            raise AttributeError
        self.goal_ext = np.random.uniform(-1.0, 1.0, (1, self.brain.dim_s_extero)).T

    def sample(self):
        # now cartesian angular motion is in s_pred, need to change that to proprio
        # FIXME: all hardcoded stuff
        cond = np.vstack((self.brain.smdict["s_extero"], self.brain.smdict["s_proprio"]))
        # print "cond", cond
        self.goal_ext = np.random.uniform(-1.0, 1.0, (1, self.brain.dim_s_extero)).T
        cond[:self.brain.dim_s_extero] = self.goal_ext
        # np.random.uniform([0, -1], [1, 1], (1, 2)).T
        cond[2:] = np.nan
        if self.brain.e2p.fitted:
            if hasattr(self.brain.e2p, "cen_lst"):
                print "%s.sample: brain.e2p fitted" % (self.__class__.__name__)
                ret = self.brain.e2p.predict(cond).T
            else:
                ret = self.brain.e2p.predict(self.goal_ext).T
        else:
            print "%s.sample: brain.e2p unfitted" % (self.__class__.__name__)
            ret = np.random.uniform(self.goald["mins"], self.goald["maxs"], (self.goal_dims_num, 1))
        intero_pos_goal_idx = self.brain.get_sm_index("s_intero", "pos_goal", indexdim = 2)
        self.brain.smdict["s_intero"][intero_pos_goal_idx] = cond[:2]
        # intero_idx = self.brain.get_sm_index("s_intero", "j_ang_")
        # pred_idx = self.brain.get_sm_index("s_pred", "j_ang_vel_pred")
        # print "ret", ret, self.smdict["s_intero"][intero_idx]
        # print "pred_idx", pred_idx, ret.shape
        # self.smdict["s_intero"][intero_idx] = ret.reshape((self.dim_s_motor, 1))
        # self.smdict["s_pred"] = ret.reshape((self.dim_s_motor, 1)) #[pred_idx]

        # ret = np.random.uniform(self.goald["mins"], self.goald["maxs"], (self.goal_dims_num, 1))
        print "%s.sample: goal = %s/%s" % (self.__class__.__name__, ret.shape, ret)
        self.goal = ret
        return self.goal
        # return ret

class AvgErrorExteroPosGoal(ExteroPosGoal):
    """Average error position goal, if the average error is below a theshold 'thresh'
    sample a new goal"""
    def __init__(self, conf):
        ExteroPosGoal.__init__(self, conf)
        self.avgerror_prop = 0.0 # force resample
        self.avgerror_ext  = 0.0 #
        self.avgerror_prop_ = 0.0 # t - 1
        self.avgerror_ext_  = 0.0 #
        self.davgerror_prop = 0.0 # deriv
        self.davgerror_ext  = 0.0 #
        self.avgderror_prop = 0.0 # avgderiv
        self.avgderror_ext  = 0.0 #
        # difference
        # avg difference
        # FIXME: generic function to compute: error, avg error, error derivative, avg error derivative, then replace error with some signal
        self.coeff = 0.1
        self.dcoeff = 0.025
        self.cnt = 0
        # FIXME: rather use average change in error

    def sample(self):
        # compute the average error
        self.avgerror_prop_ = self.avgerror_prop # store last timestep
        self.avgerror_prop = self.avgerror_prop * (1 - self.coeff) + self.brain.smdict["s_reward"] * self.coeff
        self.davgerror_prop = self.avgerror_prop - self.avgerror_prop_
        self.avgderror_prop = self.avgderror_prop * (1 - self.dcoeff) + self.davgerror_prop * self.dcoeff
        # # log average error to sm space
        # avgerrpropidx = self.brain.get_sm_index("s_intero", "avgerrorposgoal_avgerror", indexdim = 1)
        # self.brain.smdict["s_intero"][avgerrpropidx] = self.avgerror_prop

        self.avgerror_ext_ = self.avgerror_ext # store last timestep
        exterr = np.sum(np.square((self.brain.smdict["s_extero"] - self.goal_ext)))
        self.avgerror_ext  = self.avgerror_ext * (1 - self.coeff) + exterr * self.coeff
        self.davgerror_ext = self.avgerror_ext - self.avgerror_ext_
        self.avgderror_ext = self.avgderror_ext * (1 - self.dcoeff) + self.davgerror_ext * self.dcoeff

        # log average error to sm space
        locallogitems = ["avgerror_prop", "avgerror_ext", "davgerror_prop", "davgerror_ext", "avgderror_prop", "avgderror_ext"]
        for logitem in locallogitems:
            avgerrextidx = self.brain.get_sm_index_single("s_intero", logitem)
            # print "%s.sample avgerrextidx = %s" % (self.__class__.__name__, avgerrextidx)
            # self.brain.smdict["s_intero"][avgerrextidx] = self.avgerror_ext
            self.brain.smdict["s_intero"][avgerrextidx] = getattr(self, logitem)

        # check if threshold exceeded
        if (self.cnt == 0 or self.cnt > 100) and self.cnt % 10 == 0:
            # error is small enough to consider having reached the goal, sample new goal
            if self.avgerror_prop < self.thresh and self.avgerror_ext < self.thresh:
                self.goal = ExteroPosGoal.sample(self)
            elif self.avgerror_ext > 0.01:
                print "%s.sample large error e = %f, de = %f" % (self.__class__.__name__, self.avgerror_ext, self.avgderror_ext)
                # error is large and does not change so goal is probably unreachable, try a new one
                # if np.abs(self.avgderror_ext) < 0.02:
                if self.avgderror_ext > -0.025:
                    self.goal = ExteroPosGoal.sample(self)

        # FIXME: shouldn't we be logging the goal here?
        print "self.goal = %s" % self.goal
        return self.goal


text:
import Data.Binary
import Data.Binary.Get
import Data.Binary.Put
import qualified Data.ByteString.Lazy as BS
import Data.ByteString.Lazy (ByteString)
import System.Environment
import System.FilePath
import System.IO

data BMPHeader = BMPHeader {
    bm :: Word16,
    size :: Word32,
    u1 :: Word16,
    u2 :: Word16,
    offset :: Word32
} deriving (Show)

data DIBHeader = DIBHeader {
    headerSize :: Word32,
    width :: Word32,
    height :: Word32,
    planes :: Word16,
    bpp :: Word16,
    compression :: Word32,
    dataSize :: Word32,
    ppmh :: Word32,
    ppmv :: Word32,
    palleteSize :: Word32,
    important :: Word32
} deriving (Show)

data Bitmap = Bitmap {
   bmp :: BMPHeader,
   dib :: DIBHeader,
   bytes :: ByteString
}

data BGRPixel = BGRPixel {
   b :: Word8,
   g :: Word8,
   r :: Word8
}

type BGR = ([Word8], [Word8], [Word8])
type BGRList = [[Word8]]

getBMPHeader :: Get BMPHeader
getBMPHeader = do
    bm <- getWord16le
    size <- getWord32le
    u1 <- getWord16le
    u2 <- getWord16le
    offset <- getWord32le
    return $ BMPHeader bm size u1 u2 offset

getDIBHeader :: Get DIBHeader
getDIBHeader = do
    headerSize <- getWord32le
    width <- getWord32le
    height <- getWord32le
    planes <- getWord16le
    bpp <- getWord16le
    compression <- getWord32le
    dataSize <- getWord32le
    ppmh <- getWord32le
    ppmv <- getWord32le
    palleteSize <- getWord32le
    important <- getWord32le
    return (DIBHeader headerSize width height planes bpp compression dataSize
            ppmh ppmv palleteSize important)

getHeaders :: Get (BMPHeader, DIBHeader)
getHeaders = do
    b <- getBMPHeader
    d <- getDIBHeader
    return (b, d)

getBitmap :: ByteString -> Bitmap
getBitmap bytes = let
    (b, d) = runGet getHeaders bytes
    o = fromIntegral $ offset b
    in Bitmap b d (BS.drop o bytes)

bmpWidth :: Bitmap -> Int
bmpWidth bmp = fromIntegral $ width (dib bmp)

bytesPerPixel :: Bitmap -> Int
bytesPerPixel bmp = bitsPerPixel `div` 8
    where bitsPerPixel = fromIntegral $ bpp (dib bmp)

padding :: Int -> Int -> Int
padding width bpp  = (4 - (width*bpp `mod` 4)) `mod` 4

getRows :: Int -> Int -> [Word8] -> [[Word8]]
getRows _ _ [] = []
getRows width bpp bytes = row:(getRows width bpp remainder)
    where p = padding width bpp
          size = width * bpp
          (padded, remainder) = splitAt (size+p) bytes
          row = take size padded

rowToPixels :: [Word8] -> [BGRPixel]
rowToPixels [] = []
rowToPixels row = let
    ([b, g, r], remainder) = splitAt 3 row
    in (BGRPixel b g r):(rowToPixels remainder)

getPixels :: Bitmap -> [BGRPixel]
getPixels bmp = let
    w = bmpWidth bmp
    bpp = bytesPerPixel bmp
    rows = getRows w bpp . BS.unpack $ bytes bmp
    in concat $ map rowToPixels rows

splitBGR :: [BGRPixel] -> BGR
splitBGR [] = ([], [], [])
splitBGR (BGRPixel b g r:ps) = (b:bs, g:gs, r:rs)
    where (bs, gs, rs) = splitBGR ps

toList :: (a, a, a) -> [a]
toList (b, g, r) = [b, g, r]

bmpToBGR :: Bitmap -> BGR
bmpToBGR = splitBGR . getPixels

toFloat :: Word8 -> Float
toFloat color = fromIntegral color / 255

closeAll :: [Handle] -> IO [()]
closeAll handlers = sequence $ map hClose handlers

openAll :: [String] -> IO [Handle]
openAll filenames = sequence [openFile filename WriteMode |
                              filename <- filenames]

outputAll :: (Handle -> a -> IO ()) -> [Handle] -> [a] -> IO [()]
outputAll outputFunction filenames contents = do
    sequence [outputFunction filename contents |
              (filename, contents) <- zip filenames contents]

suffixes :: [String]
suffixes = ["_blue.out", "_green.out", "_red.out"]

concatSuffixes :: [String] -> String -> [String]
concatSuffixes suffixes prefix = map (prefix++) suffixes

outnames :: String -> [FilePath]
outnames = concatSuffixes suffixes

splitFileText :: String -> Bitmap -> IO ()
splitFileText prefix bitmap = do
    outputs <- openAll $ outnames prefix

    outputAll hPrint outputs $ [map toFloat color |
                                color <- toList $ bmpToBGR bitmap]

    closeAll outputs

    return ()

-- Trabalho termina aqui, geração de imagens não é necessária

putBMPHeader :: BMPHeader -> Put
putBMPHeader b = do
    putWord16le $ bm b
    putWord32le $ size b
    putWord16le $ u1 b
    putWord16le $ u2 b
    putWord32le $ offset b

putDIBHeader :: DIBHeader -> Put
putDIBHeader d = do
    putWord32le $ headerSize d
    putWord32le $ width d
    putWord32le $ height d
    putWord16le $ planes d
    putWord16le $ bpp d
    putWord32le $ compression d
    putWord32le $ dataSize d
    putWord32le $ ppmh d
    putWord32le $ ppmv d
    putWord32le $ palleteSize d
    putWord32le $ important d

putBitmap :: Bitmap -> Put
putBitmap bitmap = do
    putBMPHeader $ bmp bitmap
    putDIBHeader $ dib bitmap
    putLazyByteString $ bytes bitmap

bitmapToBS :: Bitmap -> ByteString
bitmapToBS bmp = runPut $ putBitmap bmp

padBGR :: ([Word8], [Word8], [Word8]) -> ([BGRPixel], [BGRPixel], [BGRPixel])
padBGR ([], [], []) = ([], [], [])
padBGR (b:bs, g:gs, r:rs) = (BGRPixel b 0 0:pbs,
                             BGRPixel 0 g 0:pgs,
                             BGRPixel 0 0 r:prs)
    where (pbs, pgs, prs) = padBGR (bs, gs, rs)

makePadding :: Int -> Int -> [Word8]
makePadding width bpp = take (padding width bpp) (repeat 0)

pixelsToRows :: Int -> [BGRPixel] -> [[BGRPixel]]
pixelsToRows _ [] = []
pixelsToRows width pixels = row:pixelsToRows width remainder
    where (row, remainder) = splitAt width pixels

rowToBytes :: Int -> [BGRPixel] -> [Word8]
rowToBytes width [] = makePadding width 3
rowToBytes width (BGRPixel b g r:ps) = b:g:r:rowToBytes width ps

pixelsToBytes :: Int -> [BGRPixel] -> [Word8]
pixelsToBytes width pixels = concat $ map (rowToBytes width) rows
    where rows = pixelsToRows width pixels

splitImages :: Bitmap -> (Bitmap, Bitmap, Bitmap)
splitImages bmp = let
    Bitmap bh dh _ = bmp
    BMPHeader bm size u1 u2 offset = bh
    newbh = BMPHeader bm (size-(offset-54)) u1 u2 54
    w = bmpWidth bmp
    (b, g, r) = padBGR $ bmpToBGR bmp
    in (Bitmap newbh dh . BS.pack $ pixelsToBytes w b,
        Bitmap newbh dh . BS.pack $ pixelsToBytes w g,
        Bitmap newbh dh . BS.pack $ pixelsToBytes w r)

imageSuffixes :: [String]
imageSuffixes = ["_blue.bmp", "_green.bmp", "_red.bmp"]

imagenames :: String -> [String]
imagenames = concatSuffixes imageSuffixes

splitFileImages :: String -> Bitmap -> IO ()
splitFileImages prefix bitmap = do
    outputImages <- openAll $ imagenames prefix

    outputAll BS.hPut outputImages $ [bitmapToBS b |
                                      b <- toList $ splitImages bitmap]

    closeAll outputImages

    return ()

main = do
    args <- getArgs
    case args of
        [filename] -> do
            input <- BS.readFile filename

            let prefix = takeBaseName filename
            let bitmap = getBitmap input

            -- putStrLn $ show . offset $ bmp bitmap
            splitFileText prefix bitmap
            splitFileImages prefix bitmap
        _ -> putStrLn "Usage: ./splitrgb FILE.bmp"


text:
import PIL.Image
import pytest

import torch

from prototype_common_utils import make_bounding_box, make_detection_mask, make_image

from torchvision.prototype import features
from torchvision.prototype.transforms._utils import has_all, has_any
from torchvision.prototype.transforms.functional import to_image_pil

IMAGE = make_image(color_space=features.ColorSpace.RGB)
BOUNDING_BOX = make_bounding_box(format=features.BoundingBoxFormat.XYXY, spatial_size=IMAGE.spatial_size)
MASK = make_detection_mask(size=IMAGE.spatial_size)

@pytest.mark.parametrize(
    ("sample", "types", "expected"),
    [
        ((IMAGE, BOUNDING_BOX, MASK), (features.Image,), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox,), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.Mask,), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.BoundingBox), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.Mask), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox, features.Mask), True),
        ((MASK,), (features.Image, features.BoundingBox), False),
        ((BOUNDING_BOX,), (features.Image, features.Mask), False),
        ((IMAGE,), (features.BoundingBox, features.Mask), False),
        (
            (IMAGE, BOUNDING_BOX, MASK),
            (features.Image, features.BoundingBox, features.Mask),
            True,
        ),
        ((), (features.Image, features.BoundingBox, features.Mask), False),
        ((IMAGE, BOUNDING_BOX, MASK), (lambda obj: isinstance(obj, features.Image),), True),
        ((IMAGE, BOUNDING_BOX, MASK), (lambda _: False,), False),
        ((IMAGE, BOUNDING_BOX, MASK), (lambda _: True,), True),
        ((IMAGE,), (features.Image, PIL.Image.Image, features.is_simple_tensor), True),
        ((torch.Tensor(IMAGE),), (features.Image, PIL.Image.Image, features.is_simple_tensor), True),
        ((to_image_pil(IMAGE),), (features.Image, PIL.Image.Image, features.is_simple_tensor), True),
    ],
)
def test_has_any(sample, types, expected):
    assert has_any(sample, *types) is expected

@pytest.mark.parametrize(
    ("sample", "types", "expected"),
    [
        ((IMAGE, BOUNDING_BOX, MASK), (features.Image,), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox,), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.Mask,), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.BoundingBox), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.Mask), True),
        ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox, features.Mask), True),
        (
            (IMAGE, BOUNDING_BOX, MASK),
            (features.Image, features.BoundingBox, features.Mask),
            True,
        ),
        ((BOUNDING_BOX, MASK), (features.Image, features.BoundingBox), False),
        ((BOUNDING_BOX, MASK), (features.Image, features.Mask), False),
        ((IMAGE, MASK), (features.BoundingBox, features.Mask), False),
        (
            (IMAGE, BOUNDING_BOX, MASK),
            (features.Image, features.BoundingBox, features.Mask),
            True,
        ),
        ((BOUNDING_BOX, MASK), (features.Image, features.BoundingBox, features.Mask), False),
        ((IMAGE, MASK), (features.Image, features.BoundingBox, features.Mask), False),
        ((IMAGE, BOUNDING_BOX), (features.Image, features.BoundingBox, features.Mask), False),
        (
            (IMAGE, BOUNDING_BOX, MASK),
            (lambda obj: isinstance(obj, (features.Image, features.BoundingBox, features.Mask)),),
            True,
        ),
        ((IMAGE, BOUNDING_BOX, MASK), (lambda _: False,), False),
        ((IMAGE, BOUNDING_BOX, MASK), (lambda _: True,), True),
    ],
)
def test_has_all(sample, types, expected):
    assert has_all(sample, *types) is expected


text:
title: Passing the OSCP exam - a Journey
updated: 2021-03-26 20:30
layout: post
categories:
    - infosec
    - offsec
    - hack-the-box
    - oscp
---

# Introduction
Hello there, it's been a while.

A lot has happened in during the time this blog was inactive. Besides getting certified as a [Cyber Security Professional](https://www.t-systems.com/de/en/careers/entry-areas/security/cyber-security-professional-program), I also passed the [Offensive Security Certified Professional (OSCP)](https://www.offensive-security.com/pwk-oscp/) exam! In this post I want to reflect on my experience of the course and share what it took for me to pass. I also want draw a rough timeline of what I did as prep for the final exam and which resources helped me pass in addition to the course material itself.

Disclaimer: Before starting the course, I have had around 1-2 years experience in pentesting in general, though my knowledge and experience was more focused on mobile and web apps. I had a lot of experience with Linux and just a bit of knowledge of Windows.
95% of the work for the course was done in my free time while working a full-time job. I was lucky enough to get a week off of work for exam prep as well as the time for the exam itself.

# The timeline
**09/2020**
- started preparing for the course
- watched ippsec's videos on older boxes, just to get a feeling on mentality and methodology
- got a VIP subscription for Hack The Box and started working on retired machines

**10/2020**
- lab time started on 11th October
- stopped working on HTB, solely did the lab
  - did around one host per day
- worked through the script
  - started doing the excercises but stopped after the first section
  - decided that the lab report was not worth the time (hindsight is 20/20 :D)
  - ended up using it more as a reference for specific exploit scenarios (e.g. for client-side exploits)

**12/2020**
- stopped working on the lab, ended up rooting 45 hosts and accessing all available subnets
- got back to working on HTB retired machines

**01/2021**
- lab access expired in the first week of January
- learned how to exploit buffer overflows
- got a Proving Grounds Practice subscription around two weeks before the exam date
  - used these boxes as practice for the exam, exhausting all my options before taking hints and avoiding reading walkthoughs
- first exam attempt on 31st January, ended up getting 65 points and failing (and wishing that I did the lab report, hahaha)

**02/2021**
- contemplated life and questioned my skills for a good 3 weeks after the failed exam in an attempt to recharge my energy and caught up on what happened IRL in the last months I was busy with the course
- went through my notes and logs of the exam machines, seeing what I missed and got frustrated with myself again
- made a mental list of what I was lacking to focus on while practicing
- did a few HTB boxes, active ones, to avoid reading writeups and walkthroughs when I got frustrated

**03/2021**
- continued to practice on Proving Grounds, improving my cheat sheets, reviewing my notes and solidifying my methodology
- practiced the buffer overflow a few times on the day before the exam
- second exam attempt on 24th March, ended up getting 90 points and passsing! :)

# Some more thoughs
## Labs
The labs are kind of THE thing to do in this course. I improved my game immensely. I started by doing a basic nmap scan of every host on the public network before identifying a few low-hanging fruits and deciding which one the next target would be. About 20 hosts in I decided to focus a lot more on my note-taking, improving it so that I could re-exploit any of the hosts if I needed to by referencing them. The labs were definitely the most fun I've had in this course!

## Course material
I admit, I've never watched any of the videos that were provided. I skimmed through the course script but ended up referring to it when I needed guidance in specific scenarios.

## Supplemental practice, useful stuff and prep material
- 'Buffer Overflow Prep'-room on [TryHackMe](https://tryhackme.com/room/bufferoverflowprep)
- [TJNull's OSCP prep list](https://docs.google.com/spreadsheets/d/1dwSMIAPIam0PuRBkCiDI88pU3yzrqqHkDtBngUHNCw8/edit#gid=1839402159)
  - did around 90% of the windws and linux boxes
  - watched [ippsec](https://www.youtube.com/channel/UCa6eh7gCkpPo5XXUDfygQQA)'s videos on the ones I ended up not doing
- OffSec's [Proving Grounds](https://www.offensive-security.com/labs/)
  - bought subscription for the "practice" machines
  - did all of the "practice" boxes with a community rating of "easy", "intermediate" and "hard"
  - I also did some of the "very hard" boxes but found that they usually required a lot of time for additional research because the exploits were less popular or very complicated to execute
- Priv Esc courses on Udemy by Tib3rius
  - I highly recommend these, they attempt to group different kinds of exploits together, somewhat teach a enumeration "checklist", demonstate different enumeration tools and explain the vulnerabilities you can exploit (also they provide PDFs in light and - most importantly - dark mode :D)
  - [Windows](https://www.udemy.com/course/windows-privilege-escalation/)
  - [Linux](https://www.udemy.com/course/linux-privilege-escalation/)
- [HackTricks](https://book.hacktricks.xyz/)
  - outstanding searchable (also by port number) collection of cheat sheets and knowledge for all kinds of things

## Notes and organization
Taking and organizing notes is critical! I worked with CherryTree and regularly reviewed the notes I took while working on boxes, tagging the notes with relevant metadata (e.g. if the initial shell was gained by exploiting a specific CMS, I would add the name of the CMS to the tags).
I also ended up creating cheat sheets for reverse shell payloads, commands I use often and specific methodologies for different situations as well a runbook for the buffer overflow.

My notes were detailed enough for me to know:
  - how I identified the exploited vulnerability
  - which exploit I used, which changes I made to it and why
  - the steps I took to make the exploit work (e.g. msfvenom commands, starting a SMB server, etc.)
  - additional resources needed
  - links to relevant blog posts or websites
Additionally, any screenshots I need, would also be placed in the CherryTree notebook.

For each box, I created a folder with the following subfolders that have a specific purpose:
- *recon*: any relevant files I found while enumerating the host and recon tool outputs
- *exploit*: the exploit I used to gain the initial shell, I also saved a backup of the unmodified exploit so that I could easily reference any changes I made with diff
- *post*: any enum tool output and exploits I used to escalate privileges
- *logs*: logs of my tmux session, I logged every window and pane, every command issued and its output just in case I needed to refer back to it later

With all this in the bag, my exam report was written in a matter of around 3-4 hours with the help of [noraj's report templates](https://github.com/noraj/OSCP-Exam-Report-Template-Markdown). I've heard that people submit 50+ pages, mine was just around 30.

## Exam
### The first attempt
I started my first attempt at 10am on a Monday. In the days leading up to it, I was really, I mean REALLY nervous and anxious. On Saturday I bought some snacks but stress-ate almost everything on Sunday...

In hindsight, the anxiousness is what ended up being my demise (aside from deciding that drinking a coffee at 11pm and then not going to sleep was a good idea). I got really frustrated when I couldn't find anything after 4 hours after nailing the buffer overflow within an hour. It kind of set the bad mood I had even after taking a break and getting some dinner.

Before finally going to sleep at around 4am, I had 65 points, completely missing a 20-point host and the root of the 25-point host. I got up again at around 7am and proceeded to miss two obvious possible priv esc vectors (didn't have a not of exposure with Windows boxes) as well as not putting one and one together to get the initial foothold on the other 20-point host (that one really hurt my pride). Around an hour before running out of time, I saw one of the two possible vectors (the wrong one, as it turned out) and desparately tried a few exploits to no avail.

### The second attempt
The second attempt started at noon for me. After reflecting back on the first attempt, I thought that it would be best to start later to have two more "equal" blocks of time to work on hosts (13 hours on day one, 5 hours on day two) with a block of semi-scheduled sleep (6 hours) at the usual time for me instead of having just one huge block on the first day. It ended up working out perfectly.

I had 75 points secured at around 10pm and a rough draft of the report done at 1am before going to sleep. In the morning of the second day, I polished the report to a point where I would just have to correct typos, the content being done. With around 3 hours to spare, I was still missing priv esc on both a 20 and the 25-point host. I decided to go for the 25-point host and ended up getting the exploit to work (first try!) an hour before my exam time ended, bringing my point tally up to 90 points.

After having a nap, shaking off the inevitable adrenaline dump and taking a few hours to clear my head, I reread the report (a LOT!) before submitting it on the same day at around 9pm.

Just shy of 48 hours after submitting the report, I received the e-mail that I passed after coming home from work! :)

# What I whish I had known before starting the course
- The [Infosec Prep](https://discord.gg/RRgKaep)-Discord server
  - While the forums were somewhat helpful when I was stuck on a machine in the labs, people on the server generally are more helpful, actually taking the time to listen to your problem specifically, point out what you're missing and pointing you in the right direction without spoiling the solution.
  - the previous statement is also true for any boxes in Proving Grounds
  - After my failed first attempt I got together with two other students in a similar situation and worked on a few boxes together. It helped me identify holes in my methodology, learn from their approaches and generally make a few new friends!
- Actually looting the hosts you've rooted in the labs is mandatory as some hosts require credentials that can only be found on other hosts.
- In my opinion, the labs do not provide enough exposure in priv esc. Most of the Windows hosts do not require priv esc at all or have to be exploited with kernel exploits and the course material does not cover it sufficiently. While this may be realistic, it does not help with the exam. I took additional priv esc courses on Udemy to get a general idea what to even look for. For Linux, I was able to practice enough with the HTB boxes.

# What's next for me?
Now that I've passed the OSCP, had a few days off to regroup and wrote this (very therapeutic) blog post, I've decided to tackle the Hack the Box Pro Labs next. The ones I will be doing are Offshore and RastaLabs.

The ultimate goal for me is to get into Red Teaming and aquiring that OSCE3. So for now, the plan is to do another Offsec certification, starting this summer. The ones I'll be looking at first are OSWE and OSEP.

Thanks for reading! :)