As far as I can remember, PHP has always had a terrible reputation at
handling very heavy (or asynchronous) tasks. For a long while if you
wanted to parallelize long tasks you had to resort to forking through pcntl_fork
which had its own issues, and you couldn’t really handle the results of those tasks properly, etc.
As such, a habit has kind of developed where we go straight for more intricate solutions such as queuing (which just delays your task if anything), React PHP, or even using another language altogether. But PHP can do threading, and more importantly it’s a lot easier than you probably think.
In this article I’m going to dive into the pthreads extension (short for POSIX Threads). It has been around for a while (since 2012) but I feel like too many people forget it exists or assume it is going to be painful to use – mostly because the official documentation is rather slim about it.
For those not familiar with threading, the author of pthreads has a very nice summary of it which I’m just going to quote here:
Threading is about dividing your instructions into units of execution, and distributing those units among your processors and/or cores in such a way as to maximize the throughput of your application.
Now threading does not fit all use cases, you can’t just parallelize all the things and expect it to be faster, PHP or not. It is reserved for specific cases, but when in these situations, you’ll now be able to do it in PHP, with your existing domain logic.
Getting to know pthreads
Setup
First of all we need to make sure we have the extension. If you’re sailing the Homebrew version of PHP, nothing simpler, you install it like any other extension:
brew install php56-pthreads
One small note: pthreads is compiled with PHP as it requires the --with-thread-safety
flag. As such once it’s done installing you will effectively be running a different version of PHP called the ZTS (Zend Thread Safety) version. Most extensions shouldn’t care but if you do get warnings like this when running php --version
:
Error something: mcrypt was compiled with a different version of PHP
Simply reinstall the extension, per example brew reinstall php56-mcrypt
,
and you should be good to go. If you have the Blackfire extension
enabled I also recommend disabling it for now as ZTS support is still
experimental and you might encounter some issues.
Nomenclature
The pthreads extension has a lot of different concepts that aren’t necessarily explained very well and that can prove to be confusing at first. All you need to know is there are three types of classes provided by the extension:
- Threaded objects are tasks that can be threaded, they’re your jobs, what you want to execute asynchronously.
- Workers are the classes responsible for running those jobs and synchronizing their results.
- Pools are responsible for managing multiple workers and dispatching jobs between them.
And that’s all. Now, the extension provides a handful of classes, but they simply derive from those:
As you can see that in the diagram, at its core every class is a child of Threaded
,
it’s the base class of the extension. Nonetheless you will rarely use
it by itself as its children provide more convenient methods and are
generally speaking easier to deal with.
A simple asynchronous example
Note: for brevity’s sake I won’t declare properties on the classes in the examples nor add docblocks, but you totally should.
Let’s start off easy with a simple web crawling example. We’ll start by creating our job, a class extending Thread
which itself extends Threaded
. All classes extending Threaded
must have a run method defining what should be the task to thread, so in our case it’ll be a simple file_get_contents
of a Google search, to keep it simple:
<?php
class SearchGoogle extends Thread
{
public function __construct($query)
{
$this->query = $query;
}
public function run()
{
$this->html = file_get_contents('http://google.fr?q='.$this->query);
}
}
Let’s try creating an instance of this, to per example, search cats. To start the job, we call the start
method on it. It won’t return anything, but the job will start in a separate thread.
<?php
$job = new SearchGoogle('cats');
$job->start();
Now once a job is started, there are several methods you can call to check on it, such as $job->isRunning()
, but the one we want is the join
method which will make the parent thread wait for the task to be finished and “join it back” into the main thread. Basically this is what is happening:
Once join
is called, we can be sure the class is holding our results:
<?php
$job = new SearchGoogle('cats');
$job->start();
// Wait for the job to be finished and print results
$job->join();
echo $job->html;
With that in mind, we can now per example start multiple searches at the same time and get the results:
<?php
$searches = ['cats', 'dogs', 'birds'];
foreach ($searches as &$search) {
$search = new SearchGoogle($search);
$search->start();
}
foreach ($searches as $search) {
$search->join();
echo substr($search->html, 0, 20);
}
If we print out a timestamp within our job class:
public function run()
{
echo microtime(true).PHP_EOL;
$this->html = file_get_contents('http://google.fr?q='.$this->query);
}
And run our file, we’ll see that all three jobs indeed started at the same time:
$ php multiple.php
1446987102.4479
1446987102.4503
1446987102.4525
<!doctype html><html
<!doctype html><html
<!doctype html><html
Managing jobs with workers
Now this was relatively easy, but ideally you don’t want to have to manage your jobs yourself, ie. you don’t want to have to start each of them individually and then join them one by one. You might want to just, throw your jobs somewhere and let them do their thing, and then get their results when all of them are done. That’s where workers come into play.
Workers are a class on top of which you can stack jobs, to start and join all of them at once:
<?php
class Searcher extends Worker
{
public function run()
{
echo 'Running '.$this->getStacked().' jobs'.PHP_EOL;
}
}
// Stack our jobs on our worker
$worker = new Searcher();
$searches = ['dogs', 'cats', 'birds'];
foreach ($searches as &$search) {
$search = new SearchGoogle($search);
$worker->stack($search);
}
// Start all jobs
$worker->start();
// Join all jobs and close worker
$worker->shutdown();
This would print out something like this:
Running 3 jobs
1446989108.5938
1446989108.6898
1446989108.9086
Gathering the results
Now in order for our worker to keep track of the results of each of
its job, we can simply add a method on it, and call it from the jobs.
When you stack a job onto a worker, said job will then be aware of the
worker and will be able to access it through $this->worker
. So let’s do just that, and gather the HTML fetched by our jobs:
<?php
class Searcher extends Worker
{
public $data = [];
public function run()
{
echo 'Running '.$this->getStacked().' jobs'.PHP_EOL;
}
/**
* To avoid corrupting the array
* we use array_merge here instead of just
* $this->data[] = $html
*/
public function addData($data)
{
$this->data = array_merge($this->data, [$data]);
}
}
class SearchGoogle extends Threaded
{
public function __construct($query)
{
$this->query = $query;
}
public function run()
{
echo microtime(true).PHP_EOL;
$this->worker->addData(
file_get_contents('http://google.fr?q='.$this->query)
);
}
}
// Stack our jobs on our worker
$worker = new Searcher();
$searches = ['dogs', 'cats', 'birds'];
foreach ($searches as &$search) {
$search = new SearchGoogle($search);
$worker->stack($search);
}
// Start all jobs
$worker->start();
// Join all jobs and close worker
$worker->shutdown();
foreach ($worker->data as $html) {
echo substr($html, 0, 20).PHP_EOL;
}
If we run this we’ll get the proper result:
Running 3 jobs
1446989506.0509
1446989507.938
1446989510.4684
<!doctype html><html
<!doctype html><html
<!doctype html><html
Now, you may notice I’m not doing $worker->stack(new SearchGoogle($search))
.
This is because the worker has to keep track of references to its jobs,
ie. when you start the worker, all the jobs you stacked onto it have to
still reference to something in the main thread. As this is rather
cumbersome, a class was created for this, called the Pool class. Let’s look into it:
Pooling jobs
A Pool is a class whose purpose is to dispatch jobs onto one or more workers, and manage those jobs. It is described as such in the documentation:
Pooling provides a higher level abstraction of the Worker functionality, including the management of references in the way required by pthreads.
Let’s rewrite our previous example with pooling. When you create a pool you need to pass it three arguments:
- The number of workers the pool should be able to use at the same time
- The kind of worker the pool should use (a class name string)
- Facultative arguments to pass the workers when creating them
In our case we’ll use the native pool and worker class so our new instance will look like this:
<?php
$pool = new Pool(5, Worker::class);
We can then submit jobs to the pool by calling $pool->submit(<Threaded>)
.
Main difference with workers is that a job starts as soon as you submit
it to the pool, and you don’t have to handle references anymore:
<?php
// Create a pool and submit jobs to it
$pool = new Pool(5, Worker::class);
$pool->submit(new SearchGoogle('cats'));
$pool->submit(new SearchGoogle('dogs'));
$pool->submit(new SearchGoogle('birds'));
// Close the pool once done
$pool->shutdown();
If we do this, same as before, we’ll see all our jobs start at the
same time. Everything works fine. Now let’s gather the results. In order
to interact with the jobs in a pool without having to loop through
workers and such, the pool has a convenient collect
methods which acts as a filter of sorts. You’ll pass it a closure in
which you’ll return whether a job should stay in the pool or not.
Usually you return whether the job is done.
For this, pthreads provides a Collectable
class which extends Threaded
and which has two additional methods: setGarbage
and isGarbage
to mark a job as done and ready to be collected by the garbage
collector. Let’s write our own Pool class that gathers the results from
our jobs and then discards them:
<?php
class SearchPool extends Pool
{
public $data = [];
public function process()
{
// Run this loop as long as we have
// jobs in the pool
while (count($this->work)) {
$this->collect(function (SearchGoogle $job) {
// If a job was marked as done
// collect its results
if ($job->isGarbage()) {
$this->data[$job->query] = $job->html;
}
return $job->isGarbage();
});
}
// All jobs are done
// we can shutdown the pool
$this->shutdown();
return $this->data;
}
}
That also means we need to edit our SearchGoogle
job to extend Collectable
and call setGarbage
at the end of the run method:
<?php
class SearchGoogle extends Collectable
{
public function __construct($query)
{
$this->query = $query;
}
public function run()
{
echo microtime(true).PHP_EOL;
$this->html = file_get_contents('http://google.fr?q='.$this->query);
$this->setGarbage();
}
}
We can now do the following:
<?php
// Create a pool and submit jobs to it
$pool = new SearchPool(5, Worker::class);
$pool->submit(new SearchGoogle('cats'));
$pool->submit(new SearchGoogle('dogs'));
$pool->submit(new SearchGoogle('birds'));
$pool->submit(new SearchGoogle('planes'));
$pool->submit(new SearchGoogle('cars'));
$data = $pool->process();
var_dump($data);
If we run this, not only will we see that all our 5 jobs were executed at the same time, but they completed at the same time and we were able to yield their results easily:
$ time php pooling.php
1446990493.7183
1446990493.7205
1446990493.7227
1446990493.7247
1446990493.7266
array(5) {
'birds' => (53230) "<!doctype html>"...
'cats' => (53211) "<!doctype html>"...
'cars' => (53250) "<!doctype html>"...
'dogs' => (53244) "<!doctype html>"...
'planes' => (53267) "<!doctype html>"...
}
php pooling.php 0.51s user 0.03s system 100% cpu 0.940 total
Autoloading and context inheritance
All these examples were rather basic, and when you start delving into more advanced examples you’ll most likely hit one common speed-bump: child threads don’t inherit classes autoloaded in their parent’s context.

For this you can pass options to the ->start()
method of Thread
instances, which limits how much is passed from their parent:
<?php
define('MY_CONSTANT', true);
function test() {}
class Foobar {}
class Example extends Thread
{
public function run()
{
var_dump(defined('MY_CONSTANT'));
var_dump(function_exists('test'));
var_dump(class_exists('Foobar'));
}
}
// true true true
$job = new Example();
$job->start(); // default argument is PTHREADS_INHERIT_ALL
$job->join();
// false false true
$job = new Example();
$job->start(PTHREADS_INHERIT_CLASSES);
$job->join();
// true true true
$job = new Example();
$job->start(PTHREADS_INHERIT_CLASSES | PTHREADS_INHERIT_CONSTANTS | PTHREADS_INHERIT_FUNCTIONS);
$job->join();
Now let’s require something through Composer, per example symfony/var-dumper
which is a nicer-looking wrapper around var_dump
. And let’s try to use the provided dump()
function in a job:
<?php
require 'vendor/autoload.php';
class Example extends Thread
{
public function run()
{
dump('foobar');
}
}
$job = new Example();
$job->start();
$job->join();
If you do this, it’ll fail and throw the following Exception:
Class ‘Symfony\Component\VarDumper\VarDumper’ not found
Because while that class was loaded in the main thread, it wasn’t in
the child thread. Now there are multiple ways to circumvent this, the
easiest one of course is to just require 'vendor/autoload.php'
in the run
of your Job but, that is pretty disgusting.
A nicer way to go about it, is to create a Worker class dedicated to setting up autoloading before running its jobs. Same idea, but now you don’t have to require anything in any of your job classes:
<?php
class AutoloadingWorker extends Worker
{
public function run()
{
require 'vendor/autoload.php';
}
}
// Create our worker and stack our job on it
$worker = new AutoloadingWorker();
$job = new Example();
$worker->stack($job);
$worker->start();
$worker->join();
// Or use a pool and specify our custom worker
$pool = new Pool(5, AutoloadingWorker::class);
$pool->submit(new Example());
$pool->shutdown();
Which would then yield the correct result:
$ php autoloading.php "foobar"
"foobar"
The case of closures
This far we’ve been dealing with classes everywhere but closures can also be a good source of headaches if you’re not aware that context is not fully preserved. Per example here is some code that you’ll probably think should work:
<?php
class ClosureRunner extends Collectable
{
public function __construct($closure)
{
$this->closure = $closure;
}
public function run()
{
$closure = $this->closure;
$closure();
$this->setGarbage();
}
}
$foo = 'test';
$pool = new Pool(5, Worker::class);
$pool->submit(new ClosureRunner(function () use ($foo) {
var_dump($foo);
}));
$pool->shutdown();
But it won’t, because closures are compiled in the main thread with a reference to the variable there, and then passed to your job, which tries to run it in the child thread, where the reference won’t point to an existing variable. It all boils down to PHP’s difficulties to serialize closures.
That being said, there does exist a convenience method to create jobs from closures with proper serialization, through the Threaded::from
method (which means it’s available in all its children). Per example, the following would work:
<?php
$pool = new Pool(5, Worker::class);
$foo = 'test';
$pool->submit(Collectable::from(function () use ($foo) {
var_dump($foo);
$this->setGarbage();
}));
$pool->shutdown();
Synchronization and notifications
So far we haven’t shown great interest into what our child threads were doing, but a situation may arise where you need to coordinate what is happening in your main thread with what is happening in your child thread.
This is done through the wait
and notify
methods, and their related helpers such as isWaiting
.
Say per example we have something to do in the parent thread and some
other task to do in parallel in a child thread. But we need the results
from the child thread to complete our main task, in the parent thread,
we would do it like so:
<?php
class Job extends Thread
{
public function run()
{
while (!$this->isWaiting()) {
// Do some work here as long
// as we're not waiting for parent
}
$this->synchronized(function () {
$this->result = 'DONE';
$this->notify();
});
}
}
$job = new Job();
$job->start();
// Do some operation in the main thread here
sleep(1);
// Notify the child thread that we need it
// and get its results
$job->synchronized(function ($job) {
$job->wait();
echo $job->result;
}, $job);
Note how we wrap every call to wait
and notify
in a $job->synchronized()
call, this is to ensure everything is synchronized when we make these calls and that both parties are ready.
So, we do our work in the main thread, then synchronize with the job and wait for a notification, which it then sends. This is different from simply doing $job->join()
,
as your child thread won’t be merged back into the main thread, it will
continue to live its life and you can do things after your synchronized
call. To call back to our previous diagram, here’s what a notify/wait routine would look like:
This might not seem very useful at first but it can allow a lot of things. Per example we can create a very stripped down equivalent to promises through this, by creating a Promise
class that waits for its closure to be completed in a child thread to then report it to the main thread:
<?php
class Promise extends Thread
{
public function __construct(Closure $closure)
{
$this->closure = $closure;
$this->start();
}
public function run()
{
$this->synchronized(function () {
$closure = $this->closure;
$this->result = $closure();
$this->notify();
});
}
public function then(callable $callback)
{
return $this->synchronized(function () use ($callback) {
if (!$this->result) {
$this->wait();
}
$callback($this->result);
});
}
}
$promise = new Promise(function () {
return file_get_contents('http://google.fr');
});
$promise->then(function ($results) {
echo $results;
});
This also highlights something essential: waiting and notifications don’t have to be in different threads. You can make a child thread wait on itself, or on another child thread, or you can make the main thread notify all child threads, and so on.
Bonus round: threading a command bus
All the examples we’ve seen previously were very basic for the sake of comprehension. But the tasks you’d ideally want to thread are most likely much bigger than that, have more complex dependencies, and so on.
A common case for modern PHP projects is to be backed by a command bus (Laravel’s, Tactician, whatever rows your boat). Threading can easily be integrated into this context through a custom Worker class which would receive the command bus instance and execute the command, like so:
<?php
use League\Tactician\CommandBus;
class CommandBusWorker extends Worker
{
public function __construct(CommandBus $bus)
{
$this->bus = $bus;
}
public function run()
{
require 'vendor/autoload.php';
}
public function handle($command)
{
return $this->bus->handle($command);
}
}
class CommandJob extends Collectable
{
public function __construct($command)
{
$this->command = $command;
}
public function run()
{
$this->worker->handle($this->command);
}
}
$pool = new Pool(5, CommandBusWorker::class, [new CommandBus()]);
$pool->submit(new CommandJob(new Command($some, $arguments)));
$pool->submit(new CommandJob(new AnotherCommand($some, $arguments)));
And there you have it, your two commands would be threaded and would run in parallel, with all the benefits of the command bus on top of it. You could even create a special pool that would eliminate all the boilerplate:
<?php
class CommandBusPool extends Pool
{
public function __construct(CommandBus $bus)
{
parent::__construct(5, CommandBusWorker::class, [$bus]);
}
public function submit($command)
{
return parent::submit(new CommandJob($command));
}
}
$pool = new CommandBusPool(new CommandBus());
$pool->submit(new Command($some, $argument));
One thing to watch out for though: any dependencies passed to a worker like we’re doing here needs to be serializable if it is not a child of Threaded
(or a scalar). That means they must not have any properties containing
closures. If they do, the simplest way is to recreate the instances in
the child thread (through a container and service providers per
example), or any other technique to resolve the command bus instance
within the child thread.
On resources, and other pitfalls
Resources
The command bus example highlights something which you should absolutely watch out for: resources can not be passed from the main thread to child threads. This is because of limitations in the inner workings of PHP, and while it is being worked on and will work in some edge cases, it is recommended to steer clear from passing resources around between threads.
What do I mean by resources? I mean sockets, database connections, streams and so on. If you need your database in a child thread, create a worker that connects to your database in its own context. If you need a socket, same thing, connect to the socket within the child thread instead of in the main thread.
There are ways to circumvent this but you’ll save yourself major headaches by not trying to. The more you think of your child threads as a completely different context the better you’ll come off.
Data corruption
Another pitfall (which I’ve ignored in this article’s examples for
brievty) is data corruption. Say your worker holds an array which your
jobs access. If two jobs modify it at the same time, even in a way that
seems safe, your array will get corrupted.  To go around this, pthreads provides a Stackable
class which you can extend to create thread safe data synchronization, you use it as such:
<?php
class Results extends Stackable
{
}
class Job extends Thread
{
public function __construct($test)
{
$this->test = $test;
$this->start();
}
public function run()
{
$this->test[] = rand(0, 10);
}
}
$results = new Results();
$jobs = [];
while (@$i++ < 100) {
$jobs[] = new Job($results);
}
foreach ($jobs as $job) {
$job->join();
}
// Should print 100
var_dump(count($results));
If you run this you’ll get 100
as count of the array, as expected. But now try with a standard array like so $results = []
, you will get 0
, every time. Because any structure not extending Threaded
is serialized and doesn’t reference the original variable anymore, so
while its value will be correct in the child threads, it won’t be in the
main threads.
As much as possible, if you have to move around data between threads, try to always pass children of Threaded
(like Stackable
), they won’t be serialized and were made specially to be transported across threads with no data corruption or memory issues.
What are you waiting for?
So here we go, that was an in-depth introduction to threading in PHP through pthreads. I hope next time you have a bunch of things to do at the same time, you’ll think twice before discarding PHP as an option completely. Threading won’t always be the solution, it’s for specific use cases that can be split into separate units of works (hence why the command bus fits into it so nicely), but it is nonetheless a solid tool to have in your toolbox.
The pthreads extension is crazy good, it’s well maintained, it’s already compatible with PHP7 and a new version just came out – version used in this article’s examples was 2.0.10, latest is 3.0.8 for PHP7).
Even better, the extension’s repository is available on Github and it is rife with examples, documentation and explanations about the inner mechanics of it all. The author (krakjoe) also has a very good series of gists to explain the reasoning behind pthreads and threading in PHP in general, which I highly recommend.
All the examples in this article are available in a repository if you need them again.
So go away my friends, and thread carefully!
Comments


The Satoshi Cup 2020
Who likes random chances to win something? Um, everybody!
This is a game of chance. It's based on the bitcoin blockchain's hash.
There are prizes!
- 1st place - The Satoshi Cup 2020 champion NFT. Huge bragging rights.
- 2nd place - an NFT
- 3rd place - an NFT
- Participation awards - none. I don't like participation awards. In life, everybody does not get a trophy.
- Dead last - a boobie prize NFT
The upshot is...
There are 10 entry NFTs. If you hold one, you're in. You have a 1-in-10 chance of winning. The winner will be determined by the bitcoin blockchain. The last numeral in the hash of BTC block #654,941 will be the winner. If my math is correct, that block should occur on October 31, 2020. That date was chosen in celebration of the release of the Bitcoin Whitepaper on October 31, 2008.
Details
- You need to own one of the ten NFTs to be entered (WAX blockchain). I will drop them for free at https://tlk.io/nfts.
- One NFT per person.
- The "winning number" is the last numeral of BTC block #654,941. You can use any block explorer, but I like https://blockchair.com/bitcoin in this case.
- 1st place goes to whoever holds the Satoshi Cup NFT that matches the winning number.
- 2nd place goes to whoever holds the NFT that is one number under the winning number.
- 3rd place goes to whoever holds the NFT with the number two numerals under the winning number.
- The boobie prize goes to whoever is one number over the winning number. Just like in "The Price is Right"...so close, but...you still lost.
- Any conflicts...I decide.
Updates, Details, Drop Links
I'll post any updates and the airdrop links at https://tlk.io/nfts.Read What Satoshi Wrote
Since we're celebrating the Whitepaper release, read it and all of Satoshi's words, at
https://ipfs.io/ipfs/QmU...GQL
Results
The block came in on 11/01 UTC time (still 10/31 EST). The last numeral in the hash of BTC block number 654,941 was 2.
The prizes


--- title: Ubuntu 11.10 amd64 Vagrant box layout: post ---
I've just created a Vagrant box image for Ubuntu 11.10 Server on AMD64 chipsets. Feel free to use it from here:
http://dl.dropbox.com/u/3886896/oneiric64.box
Let me know how it works for you. Thanks!


MY ROLE:
User Researcher
TEAM:
Nathan Barnhart, Stacy Kellner, Amanda Yang
WHEN:
October 2019 - December 2019
TOOLS & METHODS:
- Affinity Diagrams
- Observe & Intercept
- Think-Alouds
- Storyboarding & Speed Dating
- Experience Prototyping
Most citizens have little interest in the process of developing and implementing public art.
This UX research project explores the question: “how might we get citizens more involved?”. We quickly learned that most don't care about being involved in the first place
and at first glance, this looked like a dead end. But then we asked one more “why,” and realized that lack of interest
had to do with a key need being unfulfilled - citizens needed a convenient way to learn more.
Our solution is an interactive audio installment at the site of the public art,
which presents the project's key facts and figures, while giving viewers the chance to learn more about the placement of public art.
This educational tool helps Pittsburgh residents engage more deeply with their public spaces, and may open the door to stronger participation in future public art decisions.
The Problem
The overarching goal of our research was to identify the means in which we could help citizens be more involved in the public art process - by
process, this could mean having a say in what public art work gets installed in a neighborhood, or having a part in
the maintenance and creation process.
However, we found that many people do not have any interest in being involved in the public art process.
Our research focuses on trying to identify: (a) the reasons for this lack of interest, and (b) a potential solution to help bolster
this interest.
Methods and the Research Process
Late October 2019
Observe & Intercept, Affinity Diagramming
We conducted intercepts primarily around the Agnes R. Katz Plaza in downtown Pittsburgh
in order to gain a general understanding of our problem space, and to gauge citizens' interest
with public art or its process.
Our intercepts focused on asking questions to do with:
- (a) individual personal definitions of public art,
- (b) whether public art is a way for a community to express itself,
- (c) individual awareness of the process of implementing public art projects, and
- (d) interest level in involvement with public art projects.
After conducting these intercepts on individuals, we derived the following insights understanding
affinity diagramming:
-
- People have a minimal interest in the public art process,
-
- Citizens’ engagement in the art selection process comes mostly in the form of negative feedback, and
-
- Citizens want to have a say in the process, but find current methods inconvenient (e.g. town hall meetings).
Early November 2019
Think-Alouds
We now wanted to explore potential reasons for this minimal interest - do citizens feel that their voices are
not heard? Do they not trust that the city will act on requests that they might have?
To investigate currently-existing applications that served to promote user engagement in city processes, we
investigated the MyBurgh mobile app, which allows users to submit a service request for anything city-related.
We conducted a series of TAP studies, primarily to identify what particular needs users had with regards
to knowing that their voice was heard by the city, or how much they trusted the city to follow through with
any sort of request in the first place.
The general insight that we found from these studies was that people do have a lot to say when it
is something they care about, but felt that there needed to be improved two-way communication between the city
and its citizens.
Mid November 2019
Storyboarding, Speed Dating
We then entered a phase of need validation. From out previous studies, we derived
a series of needs that citizens potentially have, and could be the unmet needs
that prevent citizens from wanting to be engaged with the public art process.
We created a series of storyboards, each representing a different need.
The needs we wanted to validate were:
- 1) Citizens need a more convenient way to be involved in the public art process.
- 2) Citizens would like to know their opinions about public art are valued.
-
3) Even if they generally are not very interested in public art, citizens want to know when something will impact them directly.
-
4) People need information about upcoming public art projects to be convenient.
We found that through speed dating each of our storyboards, our first, third and fourth needs were validated, and that people additionally
placed great value in human-interaction - whether this be to do with learning about public art opportunity involvement,
or about the potential art works themselves. The need to have a convenient way to be involved was also validated across
multiple participants, and hinted to us that this may be the reason why individuals did not feel compelled to be involved
in the public art process -
why would they want to be involved in a process that they knew nothing about?
Main Insights & Evidence
After the bulk of our research was completed, we derived a series of core insights identified throughout the entire process.
These insights would then go on to fuel our solution.
Interest is fueled by information.
"I have never thought about how [this artwork] got here."
Citizens will not want to be involved in a process they know nothing about.
Before asking them to help select future art pieces, they should be told how the current ones came to be.
Convenience is key.
"I want to go to the meetings but they always happen at a bad time."
At present, being informed is a hassle. Town hall meetings conflict with busy schedules; advertisements are few and far between. Information should be presented openly and in a digestible way.
Human interaction matters.
"I value face-to-face interaction."
In learning about public art, users preferred in-person conversations, not digital interfaces. These two-way dialogues made users feel their voices were being heard.
Engagement is not one-size-fits-all.
"Often when you go to community meetings, you get a lot of older, retired people."
Retired couples have an easier time going to town hall meetings; teenagers are fluent in social media. An individual’s preferences may even vary day-to-day; a good solution should allow for various forms of engagement.
The Solution
In response to our overarching insights, we understood that in order to promote citizen's interest in the public art process,
they would need to learn about the process first, and the means by which one would learn about this process had to be
convenient and promote human interaction as much as possible.
Our solution is an on-site display, in which the user can press a series of buttons to hear audio recordings that detail
the process and origins of a particular art piece. We opted to have someone tell this information (via audio recordings)
as it served to be a good proxy for in-human interaction, and we hoped that this form of information transfer would be much
more engaging than reading about the process on a plaque.
We additionally wanted to employ a gamification aspect, particularly to attract the younger generation (as observed from
our fourth insight, not all engagement is one-size-fits-all). We used the concept of badge collecting, in which users
would scan the QR code on the display, which would earn them a digital badge for having visited the artwork.
The application would also display all the other badges yet to be collected, and hopefully would serve as a motivator
to continue to explore more art pieces.
Here is the
[link] to the InVision prototype.
Conclusions
We brought our prototype out into the field, and found that citizens greatly enjoyed interacting with our display.
Additionally, we found that once someone stopped to listen to a recording, passer-bys would also stop, as they
were curious as to what the display was doing. So in the end, the benefits were two-fold: our prototype not only provided
an opportunity to engage and learn about the public art process, but additionally drew the attention of other users, who
otherwise may not have stopped to look at the artwork.
Overall, the entire project was a great learning experience, and really showed that citizens will demonstrate interest towards
the public art process if they are given convenient opportunities to do so. This holds great opportunity in getting
citizens involved in public art decisions, especially now that they are more familiar with the public art process itself.


contact Page
Main Nav
Home
About
Gallery
Contact
contact me!
Name: (required)
Email: (required)
Phone: (required)
Comments:


virus epidemic PEDV porcine PED strains diarrhea {border-style (). disease px;} #ffffff;} diarrhoea European Â°C USA mortality spread highly pigs clinical coronaviruses epidemics diagnosis piglets protein px; strain viral {font-family â€" Europe Vet cell confirmed countries days different feed font-size genome identified pig reported swine virulent RNA S-INDEL Table antibodies caused diseases double; gene genotype high presence samples suckling symptoms Poland United Vero Virol age border-color border-width cause characterised contaminated detection economic infected laboratory observed occurrence outbreaks pigs, replication similar solid; {font-style {font-weight (PED) Animal China Health Survival USA, and/or animals bold cases causes classified courier; diarrhoea, early em; farms gastroenteritis global losses molecular new outbreak proteins pt;} rapid seven small specific villi virus: viruses â€²


Innocentin
I see.. Lidia von Hellmann was lord of the Forest of the Dead! She was Alfred's daughter, a survivor of the tragedy of Hellmann Forest... Thank you.
Thanks to you, we know that his death wasn't in vain...
I will treasure this crucifix always!
Hmm..? Was there something else?
"Who's behind all of this?"


I am a software engineer with experience in JavaScript, React and Redux. I first developed an interest in programming during my time testing telematic systems at Mercedes-Benz. I became intrigued by how the system operated and this led me to take an Intro to Programming course where I learned basic Python and JavaScript. After completing this course I was excited to learn more and decided to take a 4 month course from Udacity focused on React.
When I am not writing code, I am usually boxing, spending time with my cat, or just enjoying life in NYC!
I am currently looking for opportunities so please feel free to contact me!
A web application inspired by Twitter that allows users to post and connect with friends.
Live GitHubA small but feature-rich JavaScript library that simplifies Redux state updates by providing immutable functions for common changes.
GitHubA web application that allows users to browse top news stories provided by The New York Times API.
Live GitHub


{% import "_includes/forms" as forms %} {% if settings.autoEmbed %}
Hi. It looks like you were previously using the Auto Embed feature, however, due to a bug that affected other Craft plugins, Auto Embed is no longer supported. Please see the docs for more information. Saving this page will make this message go away.


Royal Łazienki Museum - 2h
ul. Agrykoli 1
The vast park surrounding the summer residence of the last Polish king, Stanisław August Poniatowski, is
where Varsovians like to go for longer walks. The park is home to a winter garden, an amphitheatre, and even
a Chinese garden. The biggest attraction, however, is the park’s permanent residents: the squirrels and
peacocks. Another site worth seeing is the classicistic Palace on the Isle with its enchanting interior
design and gallery of paintings.
The park is famous for its Chopin concerts, which take place from mid-May to the end of September every
Sunday at noon and 4 pm. Come lounge on the grass and enjoy the music.
Royal Route - 1,5h
The Royal Route connects three former residences of Polish rulers: Royal Castle, Royal Łazienki and Wilanów
Palace. It is the city’s most famous route. Among the buildings lining the streets Krakowskie Przedmieście
and Nowy Świat are the Presidential Palace, the Warsaw University campus, as well as beautiful churches and
townhouses. The Route continues along the elegant and green Aleje Ujazdowskie, with embassies and ministries
situated along the way. The historical route ends at Wilanów Palace. The Route is not to be missed in the
wintertime when it is illuminated with thousands of lights as part of the Great Illumination.
Old Town and Royal Castle - 3h
A UNESCO world heritage site, the Old Town charms with its colourful townhouses and the exceptional
atmosphere of its narrow streets. When in the Old Town Market Square, you will meet a mermaid – the official
symbol of the city. Don’t forget to see the Barbican, stop by the bell on Kanonia Street, and walk along the
old city walls. You should also visit the Royal Castle. Apart from the royal apartments, the old seat of
Polish rulers also houses an art collection with paintings by Rembrandt and Bernardo Bellotto, also known as
Canaletto.
Museum of King Jan III’s Palace at Wilanów - 2,5h
ul. St. Kostki Potockiego 10/16
Wilanów Palace is a true pearl of Baroque architecture in Warsaw. Learn about King Jan III Sobieski, who
successfully fended off the Turks in the battle of Vienna and who lived in Wilanów with his beloved
Marysieńka. Take a walk in the park and tour the palace interiors; see the portrait gallery and listen to
stories of great romances. The building and the park have both kept their original form, despite the
partition, war, and occupation. Wilanów Palace is a must-see when visiting Warsaw. In the wintertime, the
venue, illuminated with thousands of lamps, transforms into the Royal Garden of Lights.


Page intro text something will come here
Categories
Volunteer
Location
Language
Time Left
Percent Funded
Funding Status
-
Most Funded
-
Near Me
-
Live Feed
-
My Friends
-
-
Rs.1000
-
-
Suresh
-
Bangalore
5 Days Left
-
-
Rs.1000
-
-
Suresh
-
Bangalore
5 Days Left
-
-
Rs.1000
-
-
Suresh
-
Bangalore
5 Days Left


Source code for pyowm.observation
#!/usr/bin/env python
"""
Weather observation classes and data structures.
"""
from json import dumps, loads
from location import Location
from weather import Weather
from utils import converter
[docs]class Observation(object):
"""
A class representing the weather which is currently being observed in a certain
location in the world. The location is represented by the encapsulated
*Location* object while the observed weather data are held by the encapsulated
*Weather* object.
:param reception_time: GMT UNIXtime telling when the weather obervation has
been received from the OWM web API
:type reception_time: long/int
:param location: the *Location* relative to this observation
:type location: *Location*
:param weather: the *Weather* relative to this observation
:type weather: *Weather*
:returns: an *Observation* instance
:raises: *ValueError* when negative values are provided as reception time
"""
def __init__(self, reception_time, location, weather):
assert type(reception_time) is long or type(reception_time) is int, \
"'reception_time' must be an int/long"
if long(reception_time) < 0:
raise ValueError("'reception_time' must be greater than 0")
self.__reception_time = long(reception_time)
assert isinstance(location, Location), "'location' must be a Location object"
self.__location = location
assert isinstance(weather, Weather), "'weather' must be a Weather object"
self.__weather = weather
[docs] def get_reception_time(self, timeformat='unix'):
"""
Returns the GMT time telling when the observation has been received
from the OWM web API
:param timeformat: the format for the time value. May be:
'*unix*' (default) for UNIX time or '*iso*' for ISO8601-formatted
string in the format ``YYYY-MM-DD HH:MM:SS+00``
:type timeformat: str
:returns: a long or a str
:raises: ValueError when negative values are provided
"""
if timeformat == 'unix':
return self.__reception_time
if timeformat == 'iso':
return converter.UNIXtime_to_ISO8601(self.__reception_time)
else:
raise ValueError("Invalid value for parameter 'format'")
[docs] def get_location(self):
"""
Returns the *Location* object for this observation
:returns: the *Location* object
"""
return self.__location
[docs] def get_weather(self):
"""
Returns the *Weather* object for this observation
:returns: the *Weather* object
"""
return self.__weather
[docs] def to_JSON(self):
"""Dumps object fields into a JSON formatted string
:returns: the JSON string
"""
d = {"reception_time": self.__reception_time,
"Location": loads(self.__location.to_JSON()),
"Weather": loads(self.__weather.to_JSON())
}
return dumps(d)
[docs] def to_XML(self):
"""Dumps object fields into a XML formatted string
:returns: the XML string
"""
return '<Observation><reception_time>%s</reception_time>%s%s</Observation>' % \
(self.__reception_time, self.__location.to_XML(),
self.__weather.to_XML())
def __str__(self):
"""Redefine __str__ hook for pretty-printing of Observation instances"""
return "[Observation:\nreception time="+str(self.__reception_time)+ \
"\n"+str(self.__location)+"\n"+str(self.__weather)+"\n]"


{% extends "customerNavbar.html" %} {% block title %} Khidmat {% endblock %} {% block content %}
Good food is always cooking :) Order now to avail exclusive discounts on your favourite foods.
FoodID*
FoodID
Mode of Payment*
Rating


5 Installing Orber
5.1 Installation Process
This chapter describes how to install Orber in an Erlang Environment.
Preparation
To begin with, you must decide if you want to run Orber as a:
- Single node (non-distributed) - all communication with other Orber instances and ORB's supplied by other vendors use the OMG GIOP protocol.
- Multi node (distributed) - all Orber nodes, within the same domain, communicate via the Erlang distribution protocol. For all other Orber instances, i.e. not part of the same domain, and ORB's supplied by other vendors, the OMG GIOP protocol is used.
Which approach to use is highly implementation specific, but a few things you should consider:
- All nodes within an Orber domain should have the same security level.
- If the capacity is greater than load (volume of traffic) a single-node Orber might be a good solution.
- In some cases the distributed system architecture requires a single-node Orber installation.
- A multi-node Orber makes it possible to load balance and create a more fault tolerant system. The Objects can also have a uniform view if you use distributed Mnesia tables.
- Since the GIOP protocol creates a larger overhead than the Erlang distribution protocol, the performance will be better when communicating with Objects within the same Orber domain compared with inter ORB communication (GIOP).
You also have to decide if you want Orber to store internal data using disc_copies and/or ram_copies. Which storage type you should depends if/how you intend to use Mnesia in your application. If you intend to use disc_copies you must start with creating a Mnesia schema, which contain information about the location of the Erlang nodes where Orber is planned to be run. For more background information, see the Mnesia documentation.
In some cases it is absolutely necessary to change the default configuration of Orber. For example, if two Orber-ORB's shall be able to communicate via GIOP, they must have a unique domain domain. Consult the configuration settings section. If you encounter any problems; see the chapter about Debugging in this User's Guide.
Jump Start Orber
The easiest way to start Orber is to use orber:jump_start(Port), which start a single-node ORB with (most likely) a unique domain (i.e. "IP-number:Port"). This function may only be used during development and testing. For any other situation, install and start Orber as described in the following sections. The listen port, i.e. iiop_port configuration parameter, is set to the supplied Port.
How Orber is configured when using orber:jump_start(Port) may change at any time without warning. Hence, this operation must not be used in systems delivered to a customer.
Install Single Node Orber
Since a single node Orber communicate via the OMG GIOP protocol it is not necessary to start the Erlang distribution (i.e. using -name/-sname).
If we use ram_copies there is no need for creating a disk based schema. Simply use:
erl> mnesia:start(). erl> corba:orb_init([{domain, "MyRAMSingleNodeORB"}]). erl> orber:install([node()], [{ifr_storage_type, ram_copies}]). erl> orber:start().
If you installation requires disc_copies you must begin with creating a Mnesia schema. Otherwise, the installation is similar to a RAM installation:
erl> mnesia:create_schema([node()]). erl> mnesia:start(). erl> corba:orb_init([{domain, "MyDiskSingleNodeORB"}]). erl> orber:install([node()], [{ifr_storage_type, disc_copies}, {nameservice_storage_type, disc_copies}]). erl> orber:start().
You can still choose to store the IFR data as ram_copies, but then the data must be re-installed (i.e. invoke orber:install/2) if the node is restarted. Hence, since the IFR data is rather static you should use disc_copies. For more information see the orber section in the reference manual.
If you do not need to change Orber's configuration you can skip orb_init/1. But, you should at least set the IIOP timeout parameters.
Install RAM Based Multi Node Orber
Within a domain Orber uses the Erlang distribution protocol. Hence, you must start it first by, for example, using:
hostA> erl -sname nodeA
In this example, we assume that we want to use two nodes; nodeA and nodeB. Since Mnesia must know which other nodes should a part of the distribution we either need to add the Mnesia configuration parameter extra_db_nodes or use mnesia:change_config/2. To begin with, Mnesia must be started on all nodes before we can install Orber:
nodeA@hostA> mnesia:start(). nodeA@hostA> mnesia:change_config(extra_db_nodes, [nodeA@hostA, nodeB@hostB]).
After that the above have been repeated on nodeB we must first make sure that both nodes will use the same domain name, then we can install Orber:
nodeA@hostA> corba:orb_init([{domain, "MyRAMMultiNodeORB"}]). nodeA@hostA> orber:install([nodeA@hostA, nodeB@hostB], [{ifr_storage_type, ram_copies}]). nodeA@hostA> orber:start().
Note that you can only invoke orber:install/1/2 on one of the nodes. Now we can start Orber on the other node:
nodeB@hostB> corba:orb_init([{domain, "MyRAMMultiNodeORB"}]). nodeB@hostB> orber:start().
Install Disk Based Multi Node Orber
As for RAM based multi-node Orber installations, the Erlang distribution must be started (e.g. erl -sname nodeA). The major difference is that when it is disk based a Mnesia schema must be created:
nodeA@hostA> mnesia:create_schema([nodeA@hostA, nodeB@hostB]). nodeA@hostA> mnesia:start().
In this example, we assume that we want to use two nodes; nodeA and nodeB. Since it is not possible to create a schema on more than one node. Hence, all we have to do is to start Mnesia (i.e. invoke mnesia:start()) on nodeB.
After Mnesia have been started on all nodes, you must confirm that all nodes have the same domain name, then Orber is ready to be installed:
nodeA@hostA> corba:orb_init([{domain, "MyDiskMultiNodeORB"}]). nodeA@hostA> orber:install([nodeA@hostA, nodeB@hostB], [{ifr_storage_type, disc_copies}]). nodeA@hostA> orber:start().
Note that you can only invoke orber:install/1/2 on one of the nodes. Now we can start Orber on the other node:
nodeB@hostB> corba:orb_init([{domain, "MyDiskMultiNodeORB"}]). nodeB@hostB> orber:start().
5.2 Configuration
It is essential that one configure Orber properly, to avoid, for example, malicious attacks and automatically terminate IIOP connections no longer in use. An easy way to extract information about Orber's configuration parameters is to invoke the operation orber:info/1/2. Orber offer the following configuration parameters:
| Key | Range | Default |
| domain | string() | "ORBER" |
| iiop_port | integer() >= 0 | 4001 |
| nat_iiop_port | integer() > 0 | {local, integer(), [{integer(), integer()}]} | The same as iiop_port |
| iiop_out_ports | 0 | {integer(),integer()} | 0 |
| iiop_out_ports_attempts | integer() > 0 | 1 |
| iiop_out_ports_random | true | false | false |
| iiop_max_fragments | integer() > 0 | infinity | infinity |
| iiop_max_in_requests | integer() > 0 | infinity | infinity |
| iiop_max_in_connections | integer() > 0 | infinity |
| iiop_backlog | integer() > 0 | 5 |
| iiop_packet_size | integer() > 0 | infinity | infinity |
| ip_address | string() | {multiple, [string()]} | All interfaces |
| ip_address_local | string() | Defined by the underlying system |
| nat_ip_address | string() | {multiple, [string()]} | {local, string(), [{string(), string()}]} | The same as ip_address |
| objectkeys_gc_time | integer() > 0 | infinity | infinity |
| giop_version | {1,0} | {1,1} | {1,2} | {1,1} |
| iiop_setup_connection_timeout | integer() > 0 | infinity | infinity |
| iiop_connection_timeout | integer() > 0 | infinity | infinity |
| iiop_in_connection_timeout | integer() > 0 | infinity | infinity |
| iiop_out_keepalive | true | false | false |
| iiop_in_keepalive | true | false | false |
| iiop_timeout | integer() > 0 | infinity | infinity |
| interceptors | {native, [atom()]} | - |
| local_interceptors | {native, [atom()]} | - |
| orbInitRef | [string()] | undefined | undefined |
| orbDefaultInitRef | string() | undefined | undefined |
| orber_debug_level | 0 - 10 | 0 |
| flags | integer() >= 0 | 0 |
| iiop_acl | [{atom(), string()}] | [{atom(), string(), [string()]}] | [] |
| secure | no | ssl | no |
| ssl_generation | 2 | 3 | 2 |
| iiop_ssl_port | integer() >= 0 | 4002 |
| iiop_ssl_accept_timeout | integer() > 0 | infinity | infinity |
| iiop_ssl_backlog | integer() > 0 | 5 |
| iiop_ssl_ip_address_local | string() | Defined by the underlying system |
| nat_iiop_ssl_port | integer() > 0 | {local, integer(), [{integer(), integer()}]} | The same as iiop_ssl_port |
| ssl_server_options | list() | See the SSL application for valid options. |
| ssl_client_options | list() | See the SSL application for valid options. |
| iiop_ssl_out_keepalive | true | false | false |
| iiop_ssl_in_keepalive | true | false | false |
Comments on the table 'Orber Configuration Parameters':
- domain
- Since Orber domains, they are supposed to communicate via IIOP, MUST have unique names, communication will fail if two domains have the same name. The domain name MAY NOT contain ^G (i.e. \007).
- iiop_port
- If set to 0 the OS will pick any vacant port.
Note:On a UNIX system it is preferable to have a IIOP port higher than 1023, since it is not recommended to run Erlang as a root user. - nat_iiop_port
- The value is either an integer or {local, DefaultNATPort, [{Port, NATPort}]}. See also Firewall Configuration.
- iiop_out_ports
- When set to 0 any available port will be used. If a range is specified, Orber will only use the local ports within the interval when trying to connect to another ORB (Orber acts as a client ORB). If all ports are in use communication will fail. Hence, it is absolutely necessary to set iiop_connection_timeout as well. Otherwise, connections no longer in use will block further communication. If one use, for example, erl -orber iiop_out_ports "{5000,5020}", Orber will only use port 5000 to 5020 when connecting. If communicating via SSL, make sure you use a version that supports the local {port, Port} option. See also Firewall Configuration.
- iiop_out_ports_random
- Requires that iiop_out_ports define a port range. If that is the case Orber will select a port randomly from that sequence.
- iiop_out_ports_attempts
- Requires that iiop_out_ports define a port range. If so Orber will accept a number of timeouts, defined by this parameter, when trying to connect to another ORB.
- iiop_max_fragments
- Limits the number of IIOP fragments allowed per request.
- iiop_max_in_requests
- Limits the number of concurrent incoming requests per incoming connection.
- iiop_max_in_connections
- Limits the number of concurrent incoming connections.
- iiop_backlog
- Defines the maximum length the queue of pending incoming connections may grow to.
- iiop_packet_size
- Defines the maximum size of incoming requests. If this limit is exceeded, the connection is closed.
- ip_address
- This option is used if orber only should listen on a specific ip interface on a multi-interface host or if exported IOR:s should contain multiple components. The value is the IPv4 or IPv6 address as a string or {multiple, IPList}. The latter requires that the object is available via the all IP addresses found in the list.
- ip_address_local
- This option defines the default local interface Orber will use when connecting to another ORB via IIOP, i.e., Orber act as the client side ORB. The value is a IPv4 or IPv6 address as a string. It is possible to override ip_address_local by defining iiop_acl or passing the Orber generic interface Context. If this option is not used, the underlying OS will choose which interface to use. For more information, see the Interface Configuration section.
- nat_ip_address
- The value is the ip address as a string (IPv4 or IPv6), {multiple, IPList} or {local, DefaultNATIPAddress, [{IPAddress, NATIPAddress}]}. See also Firewall Configuration.
- objectkeys_gc_time
- This option should be set if objects are started using the option {persistent, true}. The value is integer() seconds.
- giop_version
- Defines the default GIOP protocol version.
- iiop_setup_connection_timeout
- The value is an integer (seconds) or the atom infinity. This option is only valid for client-side connections. If this option is set, attempts to connect to other ORB's will timeout after the given time limit. Note, if the time limit is large the TCP protocol may timeout before the supplied value.
- iiop_connection_timeout
- The value is an integer (timeout in seconds between 0 and 1000000) or the atom infinity. This option is only valid for client object connections, i.e., will have no effect on server connections. Setting this option will cause client connections to be terminated, if and only if, there are no pending requests. If there are a client still waiting for a reply, Orber will try again after the given seconds have passed. The main purpose for this option is to reduce the number of open connections; it is, for example, not necessary to keep a connection, only used once a day, open at all time.
- iiop_in_connection_timeout
- The same as for iiop_connection_timeout. The only difference is that this option only affects incoming connections (i.e. Orber act as server-side ORB).
- iiop_out_keepalive
- Enables periodic transmission on a connected socket, when no other data is being exchanged. If the other end does not respond, the connection is considered broken and will be terminated. When enabled the SO_KEEPALIVE socket level option is set.
- iiop_in_keepalive
- The same as for iiop_out_keepalive. The only difference is that this option only affects incoming connections.
- iiop_timeout
- The value is an integer (timeout in seconds between 0 and 1000000) or the atom infinity. This option is only valid on the client side. Setting this option, cause all intra-ORB requests to timeout and raise a system exception, e.g. TIMEOUT, if no replies are delivered within the given time limit.
- interceptors
- If one set this parameter, e.g., erl -orber interceptors "{native, ['myInterceptor']}", Orber will use the supplied interceptor(s) for all inter-ORB communication. 'myInterceptor' is the module name of the interceptor. For more information, see the interceptor chapter in the User's Guide and the Reference Manual.
- local_interceptors
- If defined, its value will be used when activating local interceptors via Orber Environment Flags. If not defined, but the flag is set, Orber will use the value of the interceptors parameter.
- orbInitRef
- Setting this option, e.g., erl -orber orbInitRef [\"NameService=corbaloc::host.com/NameService\"], will alter the location from where corba:resolve_initial_references(Key) tries to find an object matching the given Key. The keys will also appear when invoking corba:list_initial_services(). This variable overrides orbDefaultInitRef
- orbDefaultInitRef
- If a matching Key for orbInitRef is not found, and this variable is set, it determines the location from where orber:resolve_initial_references(Key) tries to find an object matching the given Key. Usage: erl -orber orbDefaultInitRef \"corbaloc::host.com\".
- orber_debug_level
- The range is 0 to 10. Using level 10 is the most verbose configuration. This option will generate reports, using the error_logger, for abnormal situations. It is not recommended to use this option for delivered systems since some of the reports is not to be considered as errors. The main purpose is to assist during development.
- flags
- No flags are activated in the default case. The available configuration settings are described in Orber Environment Flags.
- iiop_acl
- This option must be activated by setting
Orber Environment Flags parameter.
The value of this parameter shall be a list of [{Direction, Filter}]
and/or [{Direction, Filter, [Interfaces]}]. The Direction,
tcp_in, ssl_in, tcp_out or ssl_out, determines if
the Access Control List (ACL) applies to incoming or outgoing connections
and IIOP or IIOP over SSL. The Filter uses a extended format of
Classless Inter Domain Routing (CIDR). For example, "<IP_ADDRESS>" limits
the connection to that particular host, while "<IP_ADDRESS>/17" allows
connections to or from any host equal to the 17 most significant bits. Orber
also allow the user to specify a certain port or port range, for example,
"<IP_ADDRESS>/17#4001" and "<IP_ADDRESS>/17#4001/5001"
respectively. IPv4 or none compressed IPv6 strings are accepted.
The list of Interfaces, IPv4 or IPv6 strings, may only contain one address for outgoing connections. For incoming connections, the Interfaces list may contain several IP strings. If set for outgoing connections, and access is granted, Orber will use that local interface when connecting to the server-side ORB. For incoming connections, the client-side ORB is required to use one of the listed interfaces locally. If it fail to do so, access will be denied. The module orber_acl provides operations for evaluating the access control for filters and addresses. See also the Interface Configuration and Firewall Configuration chapters. - secure
- Determines the security mode Orber will use, which is either no if it is an insecure domain or the type of security mechanism used. Currently, per default, Orber is compliant with CSIv1 level 0, which means IIOP via SSL/TLS. The security chapter later in this manual describes how to get security in Orber and how the options are used.
- ssl_generation
- Defines which SSL version, i.e. available API, is installed. The default value, 2, refers to SSL-3.1 or later, but earlier than SSL-4.0. If set to 3 SSL-4.0, or later, must be available. Currently it not possible to use 1, it is only reserved for future use.
- iiop_ssl_port
- If set, the value must be an integer greater than zero and not equal to iiop_port.
- iiop_ssl_accept_timeout
- The value is an integer (timeout in seconds) or the atom infinity and determine how long the SSL handshake may take. This option should be set to avoid if a client never initiate the handshake.
- iiop_ssl_backlog
- Defines the maximum length the queue of pending incoming connections may grow to.
- iiop_ssl_ip_address_local
- This option defines the default local interface Orber will use when connecting to another ORB via IIOP SSL, i.e., Orber act as the client side ORB. The value is a IPv4 or IPv6 address as a string. It is possible to override iiop_ssl_ip_address_local by defining iiop_acl or passing the Orber generic interface Context. If this option is not used, the underlying OS will choose which interface to use. For more information, see the Interface Configuration section.
- nat_iiop_ssl_port
- If set, the value must be an integer greater than zero or {local, DefaultNATPort, [{Port, NATPort}]}. See also Firewall Configuration.
- ssl_server_options
- A list of the SSL options when Orber is the server. In general it's just to remove the 'ssl_server_' prefix from the old options, i.e. ssl_server_verify will just be verify in this option list. See the SSL application for the correct list of possible options and their values.
- ssl_client_options
- A list of the SSL options when Orber is the client. In general it's just to remove the ssl_client_ prefix from the old options, i.e. ssl_client_depth will just be depth in this option list. See the SSL application for the correct list of possible options and their values.
- iiop_ssl_out_keepalive
- Enables periodic transmission on a connected socket, when no other data is being exchanged. If the other end does not respond, the connection is considered broken and will be terminated. When enabled the SO_KEEPALIVE socket level option is set. Requires that the installed SSL version support the keepalive option and that the ssl_generation points to this version.
- iiop_ssl_in_keepalive
- The same as for iiop_ssl_out_keepalive. The only difference is that this option only affects incoming connections.
It is possible to invoke operations using the extra timeout parameter:
erl> module_interface:function(ObjRef, Timeout, ..Arguments..). erl> module_interface:function(ObjRef, [{timeout, Timeout}], ..Arguments..). erl> module_interface:function(ObjRef, ..Arguments..).
The extra Timeout argument will override the configuration parameter iiop_timeout. It is, however, not possible to use infinity to override the Timeout parameter. The Timeout option is also valid for objects which resides within the same Orber domain.
The iiop_setup_connection_timeout, iiop_timeout, iiop_connection_timeout and iiop_in_connection_timeout variables should be used. The specified values is implementation specific, i.e., WAN or LAN, but they should range from iiop_setup_connection_timeout to iiop_connection_timeout.
To change these settings in the configuration file, the -config flag must be added to the erl command. See the Reference Manual config(4) for further information. The values can also be sent separately as options to the Erlang node when it is started, see the Reference Manual erl(1) for further information.
Orber Environment Flags
The Environment Flags allows the user to activate debugging facilities or change Orber's behavior. The latter may result in that Orber is no longer compliant with the OMG standard, which may be necessary when communicating with a non-compliant ORB.
| Hexadecimal Value | OMG Compliant | Description |
| 0001 | no | Exclude CodeSet Component |
| 0002 | yes | Local Typechecking |
| 0004 | yes | Use Host Name in IOR |
| 0008 | yes | Enable NAT |
| 0020 | yes | Local Interceptors |
| 0080 | yes | Light IFR |
| 0100 | yes | Use IPv6 |
| 0200 | yes | EXIT Tolerance |
| 0400 | yes | Enable Incoming ACL |
| 0800 | yes | Enable Outgoing ACL |
| 1000 | yes | Use Current Interface in IOR |
Any combination of the flags above may be used and changes the behavior as follows:
- Exclude CodeSet Component - instruct Orber to exclude the CodeSet component in exported IOR:s. When activated, no negotiating regarding character and wide character conversions between the client and the server will occur. This flag will, most likely, cause problems if your IDL specification contains the data types wchar and/or wstring.
- Local Typechecking - If activated, parameters, replies and raised exceptions will be checked to ensure that the data is correct. If an error occurs, the error_logger is used to generate reports. One MAY NOT use this option for delivered systems due to the extra overhead. Since this option activates typechecking for all objects generated on the target node, it is also possible to use the option {local_typecheck, boolean()}, when invoking oe_create/2, oe_create_link/2, corba:create/4 or corba:create_link/4, to override the configuration parameter.
- Use Host Name in IOR - normally Orber inserts the IP-number in IOR:s when they are exported. In some cases, this will cause the clients to open two connections instead of one.
- Enable NAT - if this flag is set, it is possible to use the NAT (Network Address Translation) configuration parameters (nat_iiop_port, nat_iiop_ssl_port and nat_ip_address).
- Local Interceptors - use interceptors for local invocations.
- Light IFR - if the IFR is not explicitly used and this flag is set, Orber will use a minimal IFR to reduce memory usage and installation time.
- Use IPv6 - when this option is activated, Orber will use IPv6 for inter-ORB communication.
- EXIT Tolerance - servers will survive even though the call-back module caused an EXIT.
- Enable Incoming ACL - activates access control for incoming connections.
- Enable Outgoing ACL - activates access control for outgoing connections.
- Use Current Interface in IOR - when set, Orber will add the interface the request came via to exported local IOR:s.
Invoking the operation orber:info/1/2 will display the currently set flags in a readable way.
5.3 Firewall Configuration
Firewalls are used to protect objects from clients in other networks or sub-networks, but also to restrict which hosts internal objects may connect to (i.e. inbound protection and outbound protection). A firewall can limit access based on:
- Transport Level - performs access control decisions based on address information in TCP headers.
- Application Level - understands GIOP messages and the specific transport level inter-ORB Protocol supported e.g. IIOP.
This section describes how to configure a Transport Level firewall. It must have prior knowledge of the source to destination mappings, and conceptually has a configuration table containing tuples of the form: ({inhost:inport}, {outhost:outport}). If there are no port restrictions it is rather easy to configure the firewall. Otherwise, we must consider the following alternatives:
- Incoming Requests - Orber only uses the port-numbers specified by the configuration parameters iiop_port and iiop_ssl_port. Other ORB's may use several ports but it should be possible to change this behavior. Consult the other ORBs documentation.
- Outgoing Requests - Most ORB's, Orber included, ask the OS to supply a vacant local port when connecting to the server-side ORB. It is possible to change this behavior when using Orber (i.e. set the configuration parameter iiop_out_ports).
Using the option iiop_out_ports may result in that Orber runs out of valid ports numbers. For example, other applications may steal some of the ports or the number of concurrent outgoing connections to other ORBs may be higher than expected. To reduce, but not eliminate, the risk you should use iiop_connection_timeout.
Firewall configuration example:
# "Plain" IIOP To: Orber-IPNo:(iiop_port) From: ORB-IPNo:X To: ORB-IPNo:Z From: Orber-IPNo:(iiop_out_ports | Any Port) # IIOP via SSL To: Orber-IPNo:(iiop_port) From: ORB-IPNo:X To: Orber-IPNo:(iiop_ssl_port) From: ORB-IPNo:Y To: ORB-IPNo:Z From: Orber-IPNo:(iiop_out_ports | Any Port)
If the communication take place via a TCP Firewall with NAT (Network Address Translation), we must activate this behavior and define the external address and/or ports.
Using NAT makes it possible to use different host data for different network domains. This way we can share Internet Protocol address resources or obscure resources. To enable this feature the Enable NAT flag must be set and nat_iiop_port, nat_iiop_ssl_port and nat_ip_address configured, which maps to iiop_port, iiop_ssl_port and ip_address respectively. Hence, the firewall must be configured to translate the external to the internal representation correctly. If these NAT parameters are assigned a single port number or IP address, only those will be used when an IOR is exported to another ORB. When ip_address is set to {multiple, [IPAddress]}, nat_ip_address should be configured in the same way, so that each NAT IP address can be translated to a valid address by the firewall. If objects are supposed to be accessible via different interfaces and port, see also Interface Configuration, the options {local, DefaultNATIPAddress, [{IPAddress, NATIPAddress}]} and/or {local, DefaultNATPort, [{Port, NATPort}]} shall be used. The default NAT IP address and port, should be translated to the value of ip_address_local and the default listen port by the firewall. If the IP address and/or port is not found in the list, the default values will be inserted in the IOR. The firewall must be able to translate these correctly.
If it is necessary to limit the access to an ORB within a secure network, but other applications running on the same host may not be blocked out, one can use a Application Level firewall or Orber Access Control List (ACL). The latter makes it possible for the user to define which hosts may communicate, either as server or client, with Orber. This is achieved by defining the configuration parameter iiop_acl. The Classless Inter Domain Routing (CIDR) Filter determines which peer interfaces and ports the other ORB may use.
| Filter | Peer Interface(s) | Peer Port(s) |
| "<IP_ADDRESS>" | <IP_ADDRESS> | any |
| "<IP_ADDRESS>/8" | <IP_ADDRESS>-<IP_ADDRESS> | any |
| "<IP_ADDRESS>/8#4001" | <IP_ADDRESS>-<IP_ADDRESS> | 4001 |
| "<IP_ADDRESS>/8#4001/5001" | <IP_ADDRESS>-<IP_ADDRESS> | 4001-5001 |
Orber ACL, also allows the user to define which local interface(s) may be used, but will not detect spoofing. The operation orber_acl:match/2/3 makes it easy to verify whether access would be granted or not. For example, if Orber would be started with the ACL [{tcp_out, "<IP_ADDRESS>/8#4001/5001"}], then orber_acl:match/2 would behave as follows:
erl> orber_acl:match({11,1,1,1}, tcp_out). false erl> orber_acl:match({10,1,1,1}, tcp_out). true erl> orber_acl:match({11,1,1,1}, tcp_out, true). {false,[],0} erl> orber_acl:match({10,1,1,1}, tcp_out, true). {true,[],{4001,5001}}
Only if the returned boolean is true the extra return values makes a difference. In the example above, {true,[],{4001,5001}} means that Orber may connect to "<IP_ADDRESS>", using any local interface, if the server-side ORB listens for incoming connect requests on a port within the range 4001-5001. Note, invoking the orber_acl:match/2/3 operation, will not result in a connect attempt by Orber. The reason for this, is that this function may be used on a live node as well as in test environment. Hence, if a local interface is currently not available or no server-side ORB available via the given host/port(s), will not be detected by Orber.
5.4 Interface Configuration
In many cases it is sufficient to simply configure the underlying OS which local interfaces shall be used for all applications. But, in some cases it is required, due to, for example, the firewall configuration, that different local interfaces are used for different applications. Some times, it is even necessary to use a specific interface for a single CORBA object. This section describe how one can alter this in different ways.
The default behavior is that Orber lets the OS configuration decide which interface will be added in IOR:s exported to another ORB and the local interface used when connecting to another ORB (Orber act as client side ORB). The latter can be overridden by setting the configuration parameters iiop_ssl_ip_address_local and/or ip_address_local, which will affect IIOP via SSL and IIOP respectively. These parameters can be overridden by using the Orber generic interface Context or defining an ACL (Access Control List). The latter always takes precedence if a local interface is included (e.g. [{tcp_out, "<IP_ADDRESS>/8", ["<IP_ADDRESS>"]}]). If the interface is excluded (e.g. [{tcp_out, "<IP_ADDRESS>/8"}]), the interface chosen will, in the following order, be determined by #'IOP_ServiceContext'{}, ip_address_local/iiop_ssl_ip_address_local or the configuration of the underlying system.
Adding the interface context, for generated stubs/skeletons, is done in the following way:
Ctx = #'IOP_ServiceContext'{context_id = ?ORBER_GENERIC_CTX_ID, context_data = {interface, "<IP_ADDRESS>"}}, 'CosNaming_NamingContext':resolve(NS, [{context, [Ctx]}], Name),
It is also possible to add the context to corba:string_to_object/2, corba:resolve_initial_references/2, corba:resolve_initial_references_remote/3, corba:list_initial_services_remote/2, corba_object:not_existent/2, corba_object:non_existent/2 and corba_object:is_a/3. The operations exported by corba_object are affected if the supplied IOR is external. The function corba:string_to_object/2 might require the interface context if a corbaloc or a corbaloc string is passed (See the INS chapter), while corba:resolve_initial_references_remote/3 and corba:list_initial_services_remote/2 always connect to another ORB and it might be necessary to add the context. The remaining corba operations are affected if calls are re-directed by setting the orbInitRef and/or orbDefaultInitRef configuration parameters. For more information, see the Reference Manual for each module.
Configuring which interface(s) that shall be used when exporting an IOR to another ORB, is determined by nat_ip_address, setting the flag 16#1000 and ip_address, in that order. Orber listens for incoming connections either via all interfaces or the interface defined by ip_address. It is also possible to add and remove extra listen interfaces by using orber:add_listen_interface/2/3 and orber:remove_listen_interface/1. In this case one should set the 16#1000 flag and, if necessary, set the configuration parameters {local, DefaultNATIPAddress, [{IPAddress, NATIPAddress}]} and/or {local, DefaultNATPort, [{Port, NATPort}]}.


| Class | Description |
|---|---|
| AbstractAPIHandler<T> |
The AbstractAPIHandler implements convenience methods to minimize the code required in an actual handler.
|
| AuthLocal |
Gets a JWT based on a supplied username / password
|
| AuthLogin |
Gets a JWT based on a supplied username / password
|
| AuthLoginBasic |
Gets a JWT based on a supplied username / password
|
| AuthLogout |
Helps to logout a user who has still a valid JSON token
|
| CreateDocumentAttachment |
Handler for posting a file
|
| CreateLocalUser |
Creates a salted version of a username / password combination to be forwarded to storage for local users
|
| CreateSamlConfig | |
| DefaultJsonHandler |
Default handler when data are requested as Json and retuns as JSON Requests without body have their parameters as JSOn, so they qualify THis class handles most use cases, no empty shell classes needed
|
| ExecuteGroovy | |
| ExecuteJavaScript | |
| FetchOdata |
Deals with ODATA requests
|
| FetchOdataList |
lists out all available ODATA endpoints
|
| GenerateKeepApplicationSecret |
Generates an application secret and sends the salted hash to be stored in the database
|
| GetDesign | |
| GetDocumentAttachment |
Handler for returning a file
|
| GetDxl |
Return the entire design from cache or none if it isn’t cached but send of an request
|
| GetOdataMetadata |
Produces the XML Based meta data document
|
| GetOdataServiceInfo | |
| GetOpenAPI |
Handler for getOpenApi endpoint.
|
| Query | |
| UpdateDxl |
Sends DXL back to Domino for processing
|
| Enum | Description |
|---|---|
| RequestOptionFlags |
Check what request header or paraameters are required or default to an internal value
|


I joined the GDC as a student; it was a fun social outlet and an introduction to the industry. I needed a way to maintain the sense of community and creative energy that I experienced in school. Attending events hosted by the GDC has given me the opportunity to hear various perspectives and share stories. Sometimes, working as a graphic designer can feel isolating. It’s important to me to stay connected with the industry.
Stephanie Besselt O’Leary, CGD™
Designer & Illustrator | Member since 2002
I am a part of the GDC because I believe in collaborative synergy, the common development of best practices (regarding professionalism, ethics, and efficacy) and the concept of collective power—we are stronger together than we are as individuals.
Robert L. Peters, CGD™, FGDC
Designer & Educator | Member since 1985
I support the GDC because of the work it does to better the industry and the status of designers throughout Canada. I also appreciate the GDC’s initiatives in public education that help the general public develop a better understanding of what we, as graphic designers, creative communicators and design thinkers do.
Kevin Guenther, CGD™
Designer & Illustrator | Member since 1999
From a professional perspective, the GDC helps me connect with my industry, and from an educational perspective, I believe that I'm setting an example for my students. I encourage them to become members and take advantage of the opportunities GDC membership offers like scholarships, workshops, resources and social events that give them a chance to network with industry professionals. It gives me great pleasure to know that presently there are many professional members of the GDC that were once students of mine.
Frank Reimer, CGD™
Designer & Educator | Member since 1994
I love great design and nothing excites me more than seeing my work be a part of it. Being an associate member of the GDC supports the design community that is showcasing my talents through theirs. Now more than ever I feel the GDC plays an important role within our design community, educating and fostering the talent that will continue to help it grow.
Ian McCausland
Photographer | Member since 1989
As creative director of a team of designers for one of Manitoba's largest advertising agencies, and a GDC member for many years, I cannot overstate the importance of mentorship. Helping guide the careers of the next generation of designers is not something I take lightly. Being a member of today's creative industry can be exhilarating yet daunting for young designers—they need to seek inspiration from credible examples of excellence. And in an industry constantly in flux with trends pushing designers to explore multiple knowledge domains, having a support and reporting mechanism is more important than ever.
Ron Sawchuk, CGD™
Designer & Creative Director | Member since 1989
I’m a designer by trade and have been a member of the GDC since moving to Manitoba from the U.K. One of the key elements I need to be a successful creative is to surround myself with talented people who I admire, and who inspire me with their work, vision and dedication. The GDC provides the environment to foster these relationships and strives to share knowledge and ideas, which I believe is fundamental to the success, integrity and growth of the creative industry.
Dave Hardy, CGD™
Designer & Creative Director | Member since 2008
I joined the GDC for many reasons. My primary motivation was to align with an organization that, through membership, would provide a professional designation that could help build credibility and validate the expertise of my in-house design team. I also thought it would be an excellent place to source new talent when growing this team in the future. What I have gained is a professional network of peers who are equally committed to the discipline of graphic design.
Sylvie Desjarlais, CGD™
Designer & Creative Director | Member since 2011
The GDC embodies everything we aspire to: great design combined with ethical and professional business practices. It connects us to exceptional people across the country who share our passion and perspective. To us, membership is about participating and taking pride in our profession.
Paul Tétrault, CGD™ and Andrea Tétrault, CGD™
Designers & Creative Directors | Member since 1993
GDC® has been Canada’s national certification body for graphic and communication designers since 1956, establishing professional standards and actively regulating professional conduct. GDC® is a member-based organization of design professionals, educators, administrators, students and affiliates in communications, marketing, media and design-related fields.
The CGD™ mark is the only certification mark for graphic and visual communication design in Canada. GDC® licenses the unique CGD™ Certification mark only to designers, educators and administrators whose services meet rigorous, standardized criteria. The CGD™ certification mark is nationally recognized as the mark of professional work standards and ethical business conduct.


Fantoo is focused on growing into the SMB space. We’re working with a select few national partners to maximise competitiveness.
Co-branded collateral
Website listing
Free test accounts for Sales teams
Free test periods for trials
Flexible sales plans
Full product access, no-risk cancellations
Dedicated Fantoo support and account management for partners and your clients


The Commander XT’s will be launched at the OTC show the first week of May. The retail price for the XT1000 Kit is $14,975. This includes the XT1000, a 10kpsi BT pressure gauge & custom bracket, PC software, 1Year Support & Updates, 1 Day Install & Training (expenses included). The retail price for the XT2000, including all the above plus its control module, will have a retail price of $17,725. For the OTC & AWEA Windpower shows in May, the XT1000 Kit is $12,950 and XT2000 Kit is $14,950.


An early attempt to bind application state to an ookonsole instance. Here, the AppState instance contains a list of words. You can add Sally, or delete Fred, and the app state is updated.


This method is used to emit an event if this event doesn't exist that throw an error
this method remove an event registered if this event doesn't exist that throw an error
Generated using TypeDoc
This method is used to emit an event if this event doesn't exist that throw an error


« Documentation Home
Windows & Tabs
This documentation relates to Opera's now deprecated .oex Extension API framework for Opera versions <= 12.15 and also provided by our OEX2NEX shim library.
For the latest Opera Extensions API documentation for Opera versions > 12.15 please consult the latest Opera Extensions API documentation online.
Windows
- opera.extension.windows.create()
- Creates a new browser window.
- opera.extension.windows.getAll()
- Obtains a group of windows (window collection).
- opera.extension.windows.getLastFocused()
- Obtains the currently selected browser window, if any.
- BrowserWindow.insert()
- Inserts a tab or tab group into a browser window.
- BrowserWindow.close()
- Closes a browser window.
- BrowserWindow.focus()
- Gives focus to a browser window.
- BrowserWindow.update()
- Updates the properties of a browser window.
- BrowserWindow.id
- A unique identifier for the browser window.
- BrowserWindow.closed
- Gets the closed state of the browser window.
- BrowserWindow.focused
- Gets and sets the focused state of the browser window.
- BrowserWindow.parent
- Gets the parent window, if any.
- BrowserWindow.private
- Gets and sets the private state of the browser window.
- BrowserWindow.tabGroups
- Gets a window tab group manager.
- BrowserWindow.tabs
- Gets a window tab manager.
- BrowserWindow.height
- Sets the height of a browser window.
- BrowserWindow.width
- Sets the width of a browser window.
- BrowserWindow.top
- Sets the top offset of a browser window.
- BrowserWindow.left
- Sets the left offset of a browser window.
opera.extension.tabGroups
- opera.extension.tabGroups.create()
- Creates a new tab group.
- opera.extension.tabGroups.getAll()
- Obtains a group of tab groups (tab group collection).
- BrowserTabGroup.close()
- Closes a tab group.
- BrowserTabGroup.focus()
- Gives focus to a tab group.
- BrowserTabGroup.insert()
- Inserts a tab into a tab group.
- BrowserTabGroup.update()
- Updates the properties of a tab group.
- BrowserTabGroup.id
- Gets a unique identifier for a tab group.
- BrowserTabGroup.closed
- Gets the closed state of a tab group.
- BrowserTabGroup.collapsed
- Gets or sets the collapsed state of a tab group.
- BrowserTabGroup.browserWindow
- Gets a tab group's context window.
- BrowserTabGroup.tabs
- Gets all open tabs within a tab group.
- BrowserTabGroup.position
- Gets the position of a tab group.
opera.extension.tabs
- opera.extension.tabs.create()
- Creates a new tab.
- opera.extension.tabs.getAll()
- Obtains a group of tabs (tab collection).
- opera.extension.tabs.getFocused()
- An alias for opera.extension.tabs.getSelected()
- opera.extension.tabs.getSelected()
- Obtains the currently selected tab, if any.
- BrowserTab.close()
- Closes a tab.
- BrowserTab.focus()
- Gives focus to a tab.
- BrowserTab.update()
- Updates the properties of a tab.
- BrowserTab.id
- Gets a unique identifier for a tab.
- BrowserTab.closed
- Gets the closed state of a tab.
- BrowserTab.locked
- Gets and sets the locked state of a tab.
- BrowserTab.private
- Gets and sets the privacy mode of a tab.
- BrowserTab.selected
- Gets the selected state of a tab.
- BrowserTab.readyState
- Gets the current document readiness of a tab.
- BrowserTab.faviconUrl
- Gets the URL of a tab's favicon.
- BrowserTab.title
- Gets the title of a tab.
- BrowserTab.url
- Gets and sets the url of a tab.
- BrowserTab.browserWindow
- Gets a tab's context window.
- BrowserTab.tabGroup
- Gets the tab group for a tab.
- BrowserTab.position
- Gets the position of a tab.
- BrowserTab.focused
- Sets the focused state of a tab.
Overview
A browser window is a graphical user-interface component that can contain zero or more browser tabs or browser tab groups. Each browser window has an associated tab collection and tab group collection. A browser window is the context window of each browser tab and browser tab group within its associated tab collection and tab group collection, respectively. A collection of browser windows is referred to as a window collection.
A browser tab group is a graphical user-interface component contained within a browser window that can contain zero or more browser tabs. Each browser tab group has an associated tab collection and is associated with a context window. A browser tab group is the context tab group of each browser tab within its associated tab collection. A collection of browser tab groups is referred to as the tab group collection.
A browser tab is a graphical user-interface component that represents a single page contained within a browser window. Each browser tab is associated with a browser window and might be associated with a browser tab group. A user can switch between browser tabs to access different pages. Selecting a browser tab brings that page into focus. A collection of browser tabs is referred to as the tab collection.
Example
The following example adds a button the browser toolbar. Clicking the button creates a tab group in a collapsed state containing two tabs. Each tab has a specified URL and one of them is a private tab.
<!--
The configuration file ('config.xml').
-->
<?xml version='1.0' encoding='utf-8'?>
<widget xmlns="http://www.w3.org/ns/widgets" id="http://example.com/testextension" defaultlocale="en">
<name>Windows & Tabs test extension</name>
<description>A test extension that opens a tab group containing two tabs.</description>
<icon src="images/icon_64.png"/>
<icon src="images/icon_18.png"/>
</widget>
//
// The background process (e.g. index.html)
//
// Specify the properties of the button before creating it.
var UIItemProperties = {
disabled: false,
title: "Tab creation test",
icon: "images/icon_18.png",
onclick: function() {
// Create two tabs with specified URLs
var tab1 = opera.extension.tabs.create({url: 'http://dev.opera.com/'});
var tab2 = opera.extension.tabs.create({url: 'http://www.operamail.com/', private: true});
// Create a tab group containing the above two tabs
var tabGroup = opera.extension.tabGroups.create([tab1, tab2], {collapsed: true});
}
};
// Create the button and add it to the toolbar.
var button = opera.contexts.toolbar.createItem( UIItemProperties );
opera.contexts.toolbar.addItem(button);


February 1946
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Bhowani Junction Δ | 1956 | George Cukor | US & UK | Bhowani Junction | John Masters | 1952 | Novel |
1948–1949
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Hill 24 Doesn't Answer Giv'a 24 Eina Ona |
1955 | Thorold Dickinson | Israel | ? | Zvi Kolitz | 195? | Story |
| Exodus | 1960 | Otto Preminger | US | Exodus | Leon Uris | 1958 | Novel |
| Cast a Giant Shadow | 1966 | Melville Shavelson | US | Cast a Giant Shadow: The Story of Mickey Marcus Who Died to Save Jerusalem | Ted Berkman | 1962[1] | Non-fiction |
| Bab el shams | 2004 | Yousry Nasrallah | France, Egypt, Belgium, Denmark, Morocco | The Gate of the Sun | Elias Khoury | 1998 | Novel |
| O Jerusalem | 2006 | Élie Chouraqui | Belgium | O Jerusalem! | Larry Collins & Dominique Lapierre | 1972 | Non-fiction |
| Miral | 2010 | Julian Schnabel | UK, Israel, France | Miral | Rula Jebreal | 199? | Novel |
1948–1960
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Windom's Way | 1957 | Ronald Neame | UK | Windom's Way | James Ramsey Ullman | 195? | Novel |
| The 7th Dawn | 1964 | Lewis Gilbert | UK | The Durian Tree | Michael Keon | 1960 | Novel |
| The Virgin Soldiers | 1969 | John Dexter | UK | The Virgin Soldiers | Leslie Thomas | 1966 | Novel |
| Stand Up, Virgin Soldiers | 1977 | Norman Cohen | UK | Stand Up, Virgin Soldiers | Leslie Thomas | 1975 | Novel |
1950–1953
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Harry S. Truman: Plain Speaking * | 1976 | Daniel Petrie | US | Plain Speaking: An Oral Biography of Harry S. Truman[18] | Merle Miller | 1974 | Memoir/ Non-fiction |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Fixed Bayonets! | 1951 | Samuel Fuller | US | Immortal Sergeant ♠ | John Brophy | 194? | Novel |
| Hold Back the Night | 1956 | Allan Dwan | US | Hold Back the Night | "Pat Frank" | 1952 | Novel |
| Men in War | 1957 | Anthony Mann | US | Day Without End | Van Van Praag | 195? | Novel |
| Pork Chop Hill | 1959 | Lewis Milestone | US | Pork Chop Hill: The American Fighting Man in Action, Korea, Spring, 1953 | S.L.A. Marshall | 1956 | Non-fiction |
| Assembly 集結號 |
2007 | Feng Xiaogang | China | Guan Si 官司 |
Yang Jingyuan[3] | 199? | Novel |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| The Bridges at Toko-Ri | 1955 | Mark Robson | US | The Bridges at Toko-Ri | James Michener | 1953 | Novel |
| The Hunters | 1958 | Dick Powell | US | The Hunters | James Salter | 1956 | Novel |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Code Breakers * | 2005 | Rod Holcomb | US | A Return to Glory: the Untold Story of Honor, Dishonor, and Triumph at the United States Military Academy, 1950-53 | Bill McWilliams | 2000[1] | Non-fiction |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| The Great Impostor ♠ | 1961 | Robert Mulligan | US | The Great Impostor | Robert Crichton | 1959 | Non-fiction |
| MASH ♦[20] | 1970 | Robert Altman | US | M*A*S*H | "Richard Hooker" | 1953 | Novel |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| The Manchurian Candidate[21] | 1962 | John Frankenheimer | US | The Manchurian Candidate | Richard Condon | 1959 | Novel |
| The Hook ♠ | 1963 | George Seaton | US | L'Hameçon | "Vahé Katcha" | 195? | Novel |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Joint Security Area | 2000 | Park Chan-wook | South Korea | DMZ DMZ |
Park Sang-yeon | 1997 | Novel |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Battle Hymn | 1957 | Douglas Sirk | US | Battle Hymn | Col. Dean E. Hess | 1956 | Memoir |
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| The Last Picture Show[22] | 1971 | Peter Bogdanovich | US | The Last Picture Show | Larry McMurtry | 1966 | Novel |
| Though None Go with Me * | 2006 | Armand Mastroianni | US | Though None Go with Me | Jerry B. Jenkins | 199? | Novel |
1953–ongoing
| Film | Date | Director | Country | Source work |
Author | Date | Type |
|---|---|---|---|---|---|---|---|
| Joint Security Area | 2000 | Park Chan-wook | South Korea | DMZ DMZ |
Park Sang-yeon | 1997 | Novel |
1952


We can calculate times relative to a given date using:
| add | x | [timeunits] to | [given date] |
Suppported timeunits are: seconds, minutes, hours, days, months, years
x can be a negative number to subtract instead of add.
The fixture needs to be initialized with the date format used in your test.
| script | date time calculator fixture | dd-MM-yyyy | |||
| check | add | 1 | days to | 12-05-2001 | 13-05-2001 |
| check | add | -1 | days to | 12-05-2001 | 11-05-2001 |
| check | add | 18 | months to | 12-05-2001 | 12-11-2002 |
| check | add | -5 | years to | 01-01-2000 | 01-01-1995 |
| check | add | -48 | hours to | 01-01-2018 | 30-12-2017 |
| # Change the expected format | |||||
| set date format | HH:mm:ss | ||||
| check | add | 42 | minutes to | 11:03:00 | 11:45:00 |
| check | add | 3 | hours to | 00:00:11 | 03:00:11 |
| check | add | 90 | seconds to | 15:30:10 | 15:31:40 |


The best way to monetize your domain!
My ENS names
| Kiki.eth | price | % | |
| Rosco.eth | price | % | |
| Evert.eth | price | % | |
| Richard.eth | price | % | |
| Jenny.eth | price | % | |
| Radical.eth | price | % |
My freeholds
| Max.eth | Earned to date | At % |
| pepo.eth | Earned to date | At % |
My leaseholds
| Kiki.eth | Payed to date | At % | |
| Rosco.eth | Payed to date | At % | |
| Evert.eth | Payed to date | At % |