text:
# class `CommandProcesser`

A predefined class to help out the bot devs with an already defined
`message_create` event.

- Source : [events.py](https://github.com/HuyaneMatsu/hata/blob/master/hata/events.py)

The class is part of the wrapper's `events` extension, what can be setupped,
with [`events.setup_extension`](setup_extension.md) function. It adds more
hanlers to `client.events` and some more attributes to the client itself as
well. If you are using that function, then you skip the next part and go on
[Creating the event handler](#Creating-the-event-handler) part.

> The intro uses `client.commands` for adding commands, meanwhile this part
> of the documentation focuses just on the `CommandProcesser`'s capabilities,
> so we will use `on_command` here instead.

## Default setup

Adding it to events is simple:
```py
client.events(CommandProcesser(PREFIX))
```

After adding it should be shortcutted with the [`.shortcut`](#shortcut)
property. The reason of shortcutting is, because the object is an event
handler, so it's `__call__` method is already taken, but `.shortcut` returns
a specifalized object just for using it as a decorator.

```py
on_command=client.events.message_create.shortcut
```

> If more handler is added `client.events.message_create`, then it will be
replaced with [`asynclist`](asynclist.md), but that datatype still supports
attribute lookup from it's element with overwriting `__getattr__`.

An important note might be, that [client.events](EventDescriptor.md) returns
the object after adding, so instant shortcut is the most elegant solution:

```py
on_command=client.events(CommandProcesser(PREFIX)).shortcut
```

## Creating the event handler

Because the class has an attribute, called `__event_name__` set to
`'message_create'` means, the [`EventDescriptor`](EventDescriptor.md) will
always pick it up at the correct place.

### `CommandProcesser(self, prefix, ignorecase=True, mention_prefix=True, default_category_name=None)`

- `prefix`

Prefix is the only required argument when creating this event. It can be `str`,
`list` or `tuple` of `str`, or a `callable`, what gets called with the
`message` and should return a prefix.

- `ignorecase = True`

whther the handler should not be case sensitive when checking the `prefix`.

- `mention_prefix = True`

By default when mentioning the client at the message's start will make the
event's parser to act, like the message's content was started with it's prefix.
But the main difference is that at this case if we fail to find the command, we
will not await the [`invalid_command`](#invalid_command) branch.

- `default_category_name = None`

The [`CommandProcesser`](CommandProcesser.md)'s defaults category's future
name. Can be `None` or `str` instance.

## Calling the event handler

### `client.events.message_create(client,message)`

We can separate the flow of the event's handling on 5 steps:
- [`waitfors`](#waitfors)
- [`commands`](#commands)
- [`invalid_command`](#invalid_command)
- [`command_error`](#command_error)
- [`mention_prefix`](#mention_prefix)
- [`default_event`](#default_event)

#### waitfors

We can wait for a `message_create` event at a
[`channel`](ChannelBase.md). If we get a [message](Message.md)
at the set channel, each of it's waiter will be awaited bound to it.

Take care, nothing is filtered yet, filtering out bot message authors and
channels, where we can not send messages comes only after this.

#### commands

At this step we try to parse the message's content to 3 parts:
- prefix
- command name
- content

> The commands' names are not case sensitive. The content ends at the first
> linebreak, or at it's real end.

If the parsed `command name` points to a command, then the command will be
esured. The added commands are wrapped in [`Command`](Command.md) objects.

Commands must accept at least 2 arguments, the `client` and the `message` and
they can accept an optional thir as well, called `content`.

If we did not find the prefix we move on the
[`mention_prefix`](#default_event), then on the
[`default_event`](#default_event) part.

If we found the prefix, but the command is invalid, we move on the
[`invalid_command`](#invalid_command) case.

##### Command examples
```py
@on_command
async def say(client, message, content):
    await client.message_create(message.channel, content)
```

Content is optional.

```py
@on_command
async def ping(client, message):
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')
```

You can add a command with just a simple call as well.

```py
async def ping(client, message):
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')

on_command(ping)
```

Adding command with different name is supported too.

```py
@on_command(name='pong')
async def ping(client, message): # content is optional
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')
```

When you add a command with just a simple call, can be conbined with adding
with other keyword arguments too.

```py
async def ping(client, message): # content is optional
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')

on_command(ping, name='pong')
```

You can create a container, from what you can add each command. Keyword
arguments are supported too. `eventlist` is not `CommandProcesser` specific,
so specialized exceptions will be raised only when it is used up.

```py
from hata import eventlist, BUILTIN_EMOJIS

CAKE = BUILTIN_EMOJIS['cake']

cute_commands = eventlist()

@cute_commands
async def cake(client, message):
    await client.message_create(message.channel, CAKE.as_emoji)

@cute_commands(name='love')
async def send_love(client, message):
    channel = await client.channel_private_create(message.author)
    await client.message_create(channel, 'I love you :3')

on_command.extend(cute_commands)
```

You can mark aliases as supported as well.

```py
@on_command(aliases=['pong'])
async def ping(client, message):
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')
```

And of cource you can pass the desired category's name, or the category itself.
With using categories you can define global checks and a default check failure
handlers for them for each command at the category.

```py
@on_command(category='general')
async def ping(client, message):
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')
```

Specific checks are also supported.

```py
from hata.events import checks

@on_command(checks=[checks.guild_only()])
async def ping(client, message):
    await client.message_create(message.channel, f'{client.gateway.latency*1000.:.0f} ms')
```

If a check fails, then an `int` value is returned by it what can be modifed.
Cannot be set as negative value tho. If it is modified, then the check failure
handler will be called with that value as well.

To the check failure handler always 5 arguments are passed:

| name                  | type                  |
|-----------------------|-----------------------|
| client                | [Client](Client.md)   |
| message               | [Message](Message.md) |
| command               | [Command](Command.md) |
| content               | str                   |
| fail_identificator    | int                   |

```py
from hata import Role, Permission, WaitTillExc
from hata.events import checks

TESTER_ROLE = Role.precreate(role_id=123456789)

FAIL_IDENTIFICATOR_NO_ADMIN = 1
FAIL_IDENTIFICATOR_NO_TESTER_ROLE = 2

async def check_failure_handler(client, message, command, content, fail_identificator):
    if fail_identificator == FAIL_IDENTIFICATOR_NO_ADMIN:
        content = 'You must have administartor permission to use this command'
    elif fail_identificator == FAIL_IDENTIFICATOR_NO_TESTER_ROLE:
        content = f'You must have {TESTER_ROLE} to use this command'
    else:
        return

    await client.message_create(mesage.channel, content)

@on_command(checks = [
    checks.has_permission(Permission().update_by_keys(administrator=True), fail_identificator=FAIL_IDENTIFICATOR_NO_ADMIN),
    checks.has_role(TESTER_ROLE), fail_identificator=FAIL_IDENTIFICATOR_NO_TESTER_ROLE,
        ], check_failure_handler=check_failure_handler)
async def rawr(client, message):
    channel=message.channel
    loop=client.loop
    tasks=[]

    for client_ in channel.clients:
        if client_ is not client:
            if not channel.cached_permissions_for(client_).can_send_messages:
                continue

        task=loop.create_task(client_.message_create(channel,'Rawrr !'))
        tasks.append(task)

    try:
        await WaitTillExc(tasks,loop)
    except:
        for task in tasks:
            task.cancel()
        raise
```

At cases, when someone should not use a command, like no permission or such,
then the command should return `True` (or any int instance what evaulates to
`True`), because then the [`CommandProcesser`](CommandProcesser.md) will act,
like there is no command with that name.

```py
from hata import Client
from hata.events import ContentParser

@on_command
@ContentParser('user, flags=mna, default="client"',)
async def update_application_info(client, message, user):
    if not client.is_owner(message.author):
        return True

    if type(user) is Client:
        await user.update_application_info()
        content = f'Application info of `{user:f}` is updated succesfully!'
    else:
         content = 'I can update application info only of a client.'

    await client.message_create(message.channel, content)

    return False
```

> Returning `False` is unnecesary, becuse `None` evaluates to `False` anyways,
> but it might look cleaner to return objects of the same type.

You can also add a command with more arguments. At that case a parser function
will be generated to deal with it. Annottions and dedfault values will be
picked up as well.
```
from hata import User

@on_command
async def hug(client, message, user:User=None):
    if user is None:
        user = message.author

    await client.message_create(message.channel, f'Hugs {user:m} !')
```

Like this piece of code generates a parser, what tries to parse out a user
from mention, name and id of the next word of the content. With using a
default value, we can make sure, that the command will be called even if
the parsing fails.

Just some bultin and hata types are supported:

| type          | description                                                                                |
|---------------|---------------------------------------------------------------------------------------------------------------|
| str           | Parses the next word.                                                                                |
| int           | Converts the next word to int. The maximal length of converted ints is 100 by default, but can be changed.    |
| timedelta     |                                                                                |
| relativedelta | You must have deateutil installed.                                                                            |
| User          |                                                                                |
| Emoji         |                                                                                |
| ChannelBase   | Guild only for getting any channel of it.                                                                     |
| Role          | Guild only for getting any role of it.                                                                        |

The last argument without annotation will always mean the rest of the content
and every other argument before that will be interpretered as `str` annotation.
If you want to you can also use `*args` to receive undfined amount of parsed
arguments.
```
@on_command
async def separate(client, message, *args):
    if not args:
        result = 'Nothing to separate'
    else:
        result = ', '. join(args)
    await client.message_create(message.channel, result)
```
The parser everything within quote will interpreter as one word, for cases,
when you want to pass more words separated with space.

| input	                            | output                                        |
|-----------------------------------|-----------------------------------------------|
| 'Nekos are cute and fluffy.'	    | ('Nekos', 'are', 'cute', 'and', 'fluffy.')    |
| 'Nekos are "cute and fluffy."'	| ('Nekos', 'are', 'cute and fluffy.')          |
| '"Nekos are cute and fluffy."'	| ('Nekos are cute and fluffy.')                |

You can also specify the generated parser, with using the `Converter` object.
```py
from hata import Embed
from hata.events import Converter, ConverterFlag

@on_command
async def avatar(client, message, user : Converter('user', flags=ConverterFlag.user_default.update_by_keys(everywhere=True), default_code='message.author')):
    color = user.avatar&0xffffff
    if color==0:
        color = user.default_avatar.color

    url=user.avatar_url_as(size=4096)
    embed=Embed(f'{user:f}\'s avatar', color=color, url=url)
    embed.add_image(url)

    await client.message_create(message.channel, embed=embed)
```
By default `user` search is by searching by `mention` / `id` / `name` at the
respective guild, or private channel, but they can be disabled, or some
more option can be enabled with passing a moified converter flag. When
looking up a `user`, with using the `everywere` flag as well, will generate
a parser what will request the user by `id` if not found locally.

Converter also allows to pass `default` or `default_code` mutually exclusive
arguments, which allows you for more control over the default value.
```py
import random

@on_command
async def choose(client, message, emojis : Converter('emoji', amount=2)):
    emoji = random.choice(emojis)
    await client.message_create(message.channel, f'I choose {emoji:e} !')
```
`amount` is also a valid argument, which allows you to define how much object
you want to get. Passing amount as a `tuple` with as `(start, end)` is also
supported. (`end` can be passd as `0` as well, then it will go for as much as
it can.)

Each type has it's name at the parser and also 2 more value is supported
`content` and `rest` as well.

| type          | name          |
|---------------|---------------|
| str           | 'str'         |
| int           | 'int'         |
| timedelta     | 'tdelta'      |
| relativedelta | 'rdelta'      |
| User          | 'user         |
| Emoji         | 'emoji'       |
| ChannelBase   | 'channel'     |
| Role          | 'role'        |
| -             | 'content'     |
| -             | 'rest'        |

If there is check failure handler, then must be there a parser failure handler
as well when the user did not pass enough or correct arguments.

```py
async def on_parse_fail(client, message, command, content, args):
    emojis = args[0]
    if len(emojis)==1:
        result = 'Please pass 1 more emoji.'
    else:
        result = 'Please pass 2 emojis after the command\'s name.'

    await client.message_create(message.channel, result)

@on_command(parser_failure_handler=on_parse_fail)
async def choose(client, message, emojis : Converter('emoji', amount=2)):
    emoji = random.choice(emojis)
    await client.message_create(message.channel, f'I choose {emoji:e} !')
```

To the parser failure handler always 5 arguments are passed:

| name                  | type                  |
|-----------------------|-----------------------|
| client                | [Client](Client.md)   |
| message               | [Message](Message.md) |
| command               | [Command](Command.md) |
| content               | str                   |
| args                  | list of Any           |

#### invalid_command

If set, called when a user used our prefix, but typed a not existing command.
It can be added as any other command. It's specific name is `invalid_command`.

```py
@on_command
async def invalid_command(client, message, command, content):
    #do things
    pass
```

#### command_error

Whenever an exception occures meanwhile awaiting a command,
[`client.events.error`](EventDescriptor.md#errorclienteventerr)
will be ensured, but an another handler can be added too to
[`CommandProcesser`](CommandProcesser.md).

```py
from io import StringIO

from hata import Embed
from hata.events import Pagination

@on_command
async def command_error(client, message, command, content, exception):
    with StringIO() as buffer:
        await client.loop.render_exc_async(exception, [
            client.full_name,
            ' ignores an occured exception at command ',
            repr(command),
            '\n\nMessage details:\nGuild: ',
            repr(message.guild),
            '\nChannel: ',
            repr(message.channel),
            '\nAuthor: ',
            message.author.full_name,
            ' (',
            repr(message.author.id),
            ')\nContent: ',
            repr(content),
            '\n```py\n'], '```', file=buffer)

        buffer.seek(0)
        lines = buffer.readlines()

    pages = []

    page_length = 0
    page_contents = []

    index = 0
    limit = len(lines)

    while True:
        if index == limit:
            embed = Embed(description=''.join(page_contents))
            pages.append(embed)
            page_contents = None
            break

        line = lines[index]
        index = index+1

        line_lenth = len(line)
        # long line check, should not happen
        if line_lenth > 500:
            line = line[:500]+'...\n'
            line_lenth = 504

        if page_length+line_lenth > 1997:
            if index == limit:
                # If we are at the last element, we dont need to shard up,
                # because the last element is always '```'
                page_contents.append(line)
                embed = Embed(description=''.join(page_contents))
                pages.append(embed)
                page_contents = None
                break

            page_contents.append('```')
            embed = Embed(description=''.join(page_contents))
            pages.append(embed)

            page_contents.clear()
            page_contents.append('```py\n')
            page_contents.append(line)

            page_length = 6+line_lenth
            continue

        page_contents.append(line)
        page_length += line_lenth
        continue

    limit = len(pages)
    index = 0
    while index<limit:
        embed = pages[index]
        index += 1
        embed.add_footer(f'page {index}/{limit}')

    await Pagination(client,message.channel,pages)
```

> Pagination uses different events too, so those should be added as well, to
> make this example work. If you used `setup_extension`, then you have nothing
> to fear from.

If exception occures at `command_error`, `client.events.error` will be ensured.
Same return applies to `command_error` as at [`commands`](#commands). If
`command_error` returns a value, what evaluates to `True`, then
`client.events.error` will be called too, with the same exception. Can be
usefull for example if you want to show up exceptions only at a specific guild
or such.

#### mention_prefix

If our client is `@mentioned` at the start of the [message](Message.md),
we wil try to parse it to 3 parts:
- client's mention
- command
- content

If the parsing was successfull, we try to call the correct command, but if we
can not find it, we just move on.

#### default_event

Familiar to a normal `message_create` event. Awaited if non of the cases above
occurs.

```py
@on_command
async def default_event(client, message):
    #do things
    pass
```

## Adding events

The [`CommandProcesser`](CommandProcesser.md) class inherits
[`EventWaitforBase`](EventWaitforBase.md), what means it can `shortcut`-ted.
When it happens, a bound [`_EventCreationManager`](_EventCreationManager.md) is
returned, what acts like a wrapper for the
[`__setevent__`](#__setevent__-__delevent__) method.

### `client.message_create.__setevent__(func, name, description=None, aliases=None, category=None, checks=None, on_check_failure=None):)`

- raises : `TypeError` / `ValueError`

This method checks 4 cases:
- is `name` `'default_event'` and argcount is 2
- is `name` `'invalid_command'` and argcount is 4
- is `name` `'command_error'` and argcount is 5
- is `name` anything else and argcount is 2 or 3

If anything check fails, you might get some nice errors, like:
- `ValueError: 'default_event' expects 2 arguments (client, message).`
- `TypeError: Expected Coroutine function`
- `TypeError: Expected function, method, callable object`

## Removing events

Removing events is on the same way as adding.

### `client.message_create.__delevent__(func, name, **kwargs)`

- raises : `TypeError` / `ValueError`

First tries to find a command with the same name. If it found,
it will try to compare them.
if removing fails, raises `ValueError`

> Compares the two existing and the passed `func`, as it would be added as
> a command. If the passed `func` could not be even added as a command, will
> raise `TypeError`.

## Using waitfor

Waitfors are implemented with `WeakKeyDictionary`. Where The values are
`callables`, which should return an `awaitable` object. The keys are the
`wait where` objects, at this case [`channels`](ChannelBase.md).

### `client.events.message_create.append(target, waiter)`

The `waiter` is what will get called and the `target` is "where".
More `waiter` can be added under the same `target` too. All of them will be
awaited in a reversed order, so if wrappers can safely remove themselves
meanwhile.

### `client.events.message_create.remove(target, waiter)`

Same as adding but it removes the `waiter`. Also raises no error, if the
`waiter` is "already" removed.

### `get_waiter(self, target, waiter, by_type=False, is_method=False)`

Returns the first `waiter` what matches the criteria. If nothing is found,
what would, return `None`.

## Updating prefixes

If prefix is set with a callable, then it does not needs to be updated, except
if you want to update `ignorecase` at that case, If you passed before `str`,
`tuple` or `list` (yes, even at lists).

Upadting `mention_prefix` is simpler, just modify the attribute.

### `client.events.message_create.update_prefix(prefix, ignorecase=None)`

Sets the event's prefix to the set value. If `ignorecase` is not passed as
`True` or `False`, it will use the previously set option.

### Superclasses

- [`EventWaitforBase`](EventWaitforBase.md)

## Instance attributes

| name              | description                                                                                |
|-------------------|-----------------------------------------------------------------------------------------------|
| categories        | A sortedlist of [Category](Category.md) objects of the handler.                               |
| command_error     | The event, hat is called, when a command raised an exception.                                 |
| commands          | A dict of the added commands to the handler as (command_name, [Command](Command.md) pairs.    |
| default_event     | The default event if prefix could not be parsed.                                              |
| ignorecase        | Is prefix not-case sensitive.                                                                 |
| invalid_command   | The event what called, when prefix found, but the corresponding command not.                  |
| mention_prefix    | Are we accepting mention too as prefix.                                                       |
| prefix            | The passed prefix at creation or at update.                                                   |
| prefixfilter      | The generated function to check the prefix at the start of the message and parse it's content.|
| waitfors          | A WeakKeyDictionary to store each waitfor, in (channel, callable) pair.                       |

## Class attrbiutes

### `SUPPORTED_TYPES`

- type : `tuple`
- elements : [`Command`](Command.md)

A `tuple` of the types, what's instances the `CommandProcesser` supports
to be added with typed `eventlist`.

## Properties

### `command_count`

- returns : `int`

Returns the amount fo commands added to the handler. Do not counts aliases.

### `shortcut`

- returns : [`_EventCreationManager`](_EventCreationManager.md)

Normally the `CommandProcesser` cannot be used as a wrapper, because it's
`__call__` is needed to handle the events.  This property returns a
[`_EventCreationManager`](_EventCreationManager.md) what acts
like a wrapper for the [`__setevent__`](#__setevent__-__delevent__) method.

### `default_category_name` (get)

- returns : [`Category`](Category.md) / `None`
- default : `None`

Returns the [`CommandProcesser`](CommandProcesser.md)'s default category's
name.

### `default_catgeory_name` (set)

- raises : `TypeError` / `ValueError`

Changes the [`CommandProcesser`](CommandProcesser.md)'s default category's name
to the given value.

Can be asigned as `str` instance or as `None`. If other value is passed, raises
`TypeError`.

## Methods

### `create_category(self, name, checks=None, on_check_failure=None, description=None)`

- returns : [`Category`](Category.md)
- raises : `TypeError` / `ValueError`

Creates a category with the specified arguments. If a category exists with the
same name, raises `ValueError`.

### `delete_category(self, category)`

- returns : `None`
- raises : `TypeError` / `ValueError`

Deletes a category from the [`CommandProcesser`](CommandProcesser.md). It can
be passed as [`Category`](Category.md) or as `str` instance.

If the category is found, then every of it's commands will be removed from
the [`CommandProcesser`](CommandProcesser.md).

### `get_category(self, category_name)`

- returns : [`Category`](Category.md) / `None`
- default : `None`
- raises : `TypeError`

Returns the category for the given name. If the name is passed as `None`, then
will return the default category of the [`CommandProcesser`](CommandProcesser.md).

Accepts `None` and `str` instance. If other object is passed, raises `TypeError`.

### `get_category(self, category_name)`

- returns : [`Category`](Category.md) / `None`
- default : `None`
- raises : `TypeError`

Returns the category for the given name. If the name is passed as `None`, then
will return the default category of the [`CommandProcesser`](CommandProcesser.md).

Accepts `None` and `str` instance. If other object is passed, raises `TypeError`.

### `get_default_category(self)`

- returns : [`Category`](Category.md)

Returns the [`CommandProcesser`](CommandProcesser.md)'s default category.

## Magic Methods

### `__repr__(self)`

- returns : `str`

Returns the representation of the object.

### `__call__(self, client, message)`

- `awaitable`
- returns : `None`

Handles the incoming event.

### `__setevent__`, `__delevent__`, `__setevent_from_class__`

The internal methods to set and del events from a
[`EventWaitforBase`](EventWaitforBase.md) "subclass".

## Internal

### `_get_category_key(category)` (staticmethod)

- returns : `str`

Used as a key, when searching a category for a specific name at `.categories`.

### `_add_command(self, command)` (method)

- returns : `None`
- raises : `ValueError`

Adds the [`Command`](Command.md) to the command processer.

> If the command has category set as a [`Category`](Category.md), and the
> command processer has a different one, but with the same name, then raises
> `ValueError`

> If the command would overwrite an another command's alias, but not it's name,
> raises `ValueError`.

> If the command would overwrite more command's name, raises `ValueError`.


text:
{{{
  "title": "Partner Cloud: Requirements for Dedicated Edition",
  "date": "02-20-2017",
  "author": "Ben Swoboda",
  "attachments": [],
  "contentIsHTML": false
}}}

### Overview

Azure Cloud Integration is available for Cloud Application Manager Dedicated Edition as well as the Cloud Edition. There are special connectivity requirements that must be considered.

### Audience

Users of the Cloud Application Manager Dedicated Edition

### Prerequisites

Knowledge of how to get started with  [new cloud-optimized Azure](partner-cloud-integration-azure-new.md),  [new cloud-optimized AWS](partner-cloud-integration-aws-new.md), [existing cloud-optimized Azure](partner-cloud-integration-azure-existing.md) or [existing cloud-optimized AWS](partner-cloud-integration-aws-existing.md)

### Important Information

The Data Center Addition will need to have outbound port 443 for the following:

* https://api.ctl.io
* https://cloudintegration.ctl.io

### Contacting Cloud Application Manager Support

We’re sorry you’re having an issue in [Cloud Application Manager](https://www.ctl.io/cloud-application-manager/). Please review the [troubleshooting tips](../Troubleshooting/troubleshooting-tips.md), or contact [Cloud Application Manager<EMAIL_ADDRESS>with details and screenshots where possible.

For issues related to API calls, send the request body along with details related to the issue.

In the case of a box error, share the box in the workspace that your organization and Cloud Application Manager can access and attach the logs.
* Linux: SSH and locate the log at /var/log/elasticbox/elasticbox-agent.log
* Windows: RDP into the instance to locate the log at ProgramDataElasticBoxLogselasticbox-agent.log

repository: AnthonyHakim/PublicKB

path: /Cloud Application Manager/Cloud Optimization/partner-cloud-integration-azure-appliance.md

branch_name: refs/heads/master

extension: md

gha_license_id: NOASSERTION

license_type: permissive

repo_name: AnthonyHakim/PublicKB


text:
# Registering Your Contract's Method Names

MetaMask uses the Parity on-chain registry of function signatures to display method names on the confirm screen.
For many common method names, like token methods, this allows MetaMask to successfully look up the method names by their [method signature](https://solidity.readthedocs.io/en/v0.4.21/abi-spec.html).
However, sometimes you're using a method that is not in that on-chain registry, and MetaMask will simply display `Contract Interaction` to the user.

To add your contract's function names to this registry so it shows in the MetaMask interface, follow the below steps.

1. Go to the [Mainnet Parity signature registration contract on etherscan](https://etherscan.io/address/0x44691b39d1a75dc4e0a0346cbb15e310e6ed1e86#writeContract)

2. Connect MetaMask

3. Use etherscan's write contract feature to input the string value (without quotes or spaces) to the register function

   For example:

   `getOwners()`

   `execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)`

4. Click "write"

5. Approve the transaction in MetaMask (you only pay gas)

## Verify

`ethers.utils.keccak256('getOwners()') => 0xa0e67e2bdc0a6d8a09ccd6c353c9df590807ad66ff5e6630c4f31a86dfa84821`

- Take the first 10 characters: `0xa0e67e2b`
- Input them into [this demo app](https://jennypollack.github.io/function_signature_registry/) that checks the on-chain registry
  - Mainnet or Rinkeby only

### Using remix.ethereum.org

- Paste the contract code from [bokky's blog post](https://www.bokconsulting.com.au/blog/a-quick-look-at-paritys-signature-registry-contract/) into [remix](https://remix.ethereum.org).
- Set the correct compiler version based on the contract.
- Use remix's write functionality to add to the registry.
- You can look at the FUNCTIONHASHES section on [remix](https://remix.ethereum.org) by loading the signature registry contract, press the "details" button on the compile tab.

### Using `eth-method-registry`

- You can also use the [signature registry](https://rinkeby.etherscan.io/address/0x0c0831fb1ec7442485fb41a033ba188389a990b4) deployed on Rinkeby
  - [`eth-method-registry`](https://github.com/MetaMask/eth-method-registry) is used to lookup methods in MetaMask.
  - Note that MetaMask reads from the Mainnet `eth-method-registry` endpoint, regardless of user's network.
  - For more details, see [this StackExchange answer](https://ethereum.stackexchange.com/questions/59678/metamask-shows-unknown-function-when-calling-method-send-function).

license: MIT

gha_language: JavaScript

gha_license_id: MIT


text:
---
title: "132 - Objecttype"
menu:
  main:
    name: "Objecttype"
    identifier: "technical/types/objecttype"
    parent: "technical/types"
---
# Objecttype

Objecttypes are defined in the user [schema](/en/technical/types/schema), but main objecttypes can also have
some properties attached to them that can be changed without having any impact in the data model.
This type is used for that.

## Attributes

| Name                        | Description                                                                                |
|-----------------------------|-----------------------------------------------------------------------------------------------------------|
| `_basetype`                 | Name of the base type (string, r): **objecttype**                                                         |
| `_acl`                      | ACL (array of [acl entries](/en/technical/types/acl_entry), rw, optional)                                         |
| `_private_tags`             | Allow private tags to be set (boolean, rw, optional): defaults to **false**                               |
| `_tags`                     | Tags (array of [tag entries](/en/technical/types/tag_entry), rw, optional)                                        |
| `_maskfilters`              | Tag filters to be applied for each mask (see below, optional)                                             |
| `_columnfilters`            | Column filters (list of objects, rw, optional)                                                            |
| ↦ `internal_name`     | internal name, has to be unique for each object type (string, rw, optional)                               |
| ↦ `tagfilter`         | [tag filter](../tag_filter) |
| ↦ `who`               | list of target users, as in [ACL entry](../acl_entry) |
| ↦ `columns`           | list of column IDs |
| ↦ `system_fields`     | object with column names of system fields as boolean values (rw, optional) |
| `_transitions`              | Transitions (array of [transitions](/en/technical/types/transition), rw, optional)                                |
| `_private_transitions`      | Private transitions flag (bool, rw, optional): defaults to **false**                                      |
| `_standard_masks`           | mask order to use for this objecttype (non-empty array of integer, optional, rw): ref [mask](/en/technical/types/maskset).mask\_id. If set to **null**, the standard mask is derived from the datamodel. |
| `_export_asset_filenames`   | per-field configuration of export filename, see [below](#export_asset_filenames).                         |
| `objecttype`                | Objecttype attributes:                                                                                |
| ↦ `_id`               | Objecttype ID (integer, unique, r\*): ref [table definition](/en/technical/types/schema).table\_id          |
| ↦ `_version`          | Objecttype database version (integer, rw): detect and prevent concurrent updates.                         |
| ↦ `name`              | Objecttype name (string, unique, r): ref [table definition](/en/technical/types/schema).name                |
| ↦ `contact`           | Contact ([user (contact)](/en/technical/types/user), optional, rw)                                        |
| ↦ `mapping_image_export`     | Export mapping image to be used for this objecttype (integer/string, optional, rw): either an ID or "none"       |
| ↦ `mapping_image_import`     | Import mapping image to be used for this objecttype (integer/string, optional, rw): either an ID or "none"       |
| ↦ `mapping_dc_export`        | Dublin Core mapping to be used for this objecttype (integer/string, optional, rw): either an ID or "none"       |
| ↦ `description`       | Objecttype description ([l10n](/en/technical/types/l10n), optional, rw)                                           |
| ↦ `show_in_collections` | Flag to save whether this Objecttype will be shown in the quick access panel of the search in the frontend (boolean, optional, rw, defaults to **false**) |
| ↦ `show_in_facet_grouping` | Flag to save whether this Objecttype will be shown as a linked Objecttype in the filter tree in the frontend (boolean, optional, rw, defaults to **false**) |
| ↦ `custom_data`       | Custom JSON data, can contain any additional data for this objecttype. [Assets can be referenced](#assets-in-custom-data) using the suffix `:eas_file` (JSON object, optional, rw) |

### Remarks:

- `_id` has to be set for POST operations
- `_private_tags` and `_tags` only exist for objecttypes with `pool_link` set to **false**. See [tag management](/en/technical/tagmanagement).
- if `_standard_masks` contains a subset of all masks, only these will be indexed
- `_columnfilters.system_fields` is an object with any of the following keys for boolean values: `["parent", "owner"]` (system fields that have field rights)
  - if the value is **false** or not set, the system field will be not visible

### Assets in custom_data

Assets can be included in the `custom_data` JSON object at any key. The [asset information](/en/technical/types/asset/#attributes) can be stored directly, if it is known.

The asset can also be referenced using only the Asset ID, and the server will find the asset and include the asset information automatically. This is done on saving custom data. The JSON is enriched before it is saved in the database.

This can be triggered by using any key with the suffix `:eas_file`. The value at these keys must be a JSON map and contain the asset ID `_id` as an integer value. Multiple keys with the suffix can be used anywhere in the custom data.

**Example:**

{{< include_json "./custom_data_asset_id.json" >}}

The server reads the `_id` in the object `asset:eas_file` and looks for an asset with this ID in the database. If this asset is found, the value of `asset:eas_file` is replaced with the asset information:

{{< include_json "./custom_data_asset_information.json" >}}

If no asset with the ID can be found, the request will cause an [API Error](/en/technical/api/objecttype/#http-status-codes-1). Also, if the value of any `*:eas_file` key is not an object, or if `*:eas_file._id` is missing or is no valid integer, an API Error is caused.

## Mask filters

For each mask except the standard mask, a tag filter can be specified. When indexing objects, the newest version which fulfills the tag filter
is used (no tag filter means that the current version will be used). That means that the user can control which version of an object can be
found with a certain mask. It is possible for an object not to be indexed at all for a particular mask.

The attribute `_maskfilters` is a map from mask IDs to tag filters, like this:

{{< include_json "./maskfilters.json" >}}

### Export filename templates

`_export_asset_filenames` is an object containing a localized filename template per asset field:

{{< include_json "./export_asset_filenames.json" >}}

The given template only specifies the filename base, the file extension is automatically added. The variables replaced (`%...%`) include fields from object record (e.g. `%bilder.name%`) and some special fields (e.g. `%_export.name%`). The following special fields are recognized:

| Variable         | Description         |
|------------------|---------------------|
| `%_asset.id%`    | EAS asset ID        |
| `%_asset.class%` | asset file class    |
| `%_asset.extension%` | asset extension |
| `%_asset.original_filename%` | base of original filename of asset (without extension) |
| `%_asset.technical_metadata.height%` | height of asset |
| `%_asset.technical_metadata.max_dimension%` | bigger value of width and height |
| `%_asset.technical_metadata.width%` | width of asset |
| `%_asset.version%` | version name of asset |
| `%_export.name%` | name of export |
| `%_global_object_id%` | global object ID of record |
| `%_system.easydb.name%` | name (ID) of easydb |
| `%_system_object_id%` | system object ID of record |

## Related operations

- [/objecttype](/en/technical/api/objecttype): set/get properties of objecttypes

repository: programmfabrik/easydb-documentation

gha_language: Go

repo_name: programmfabrik/easydb-documentation


text:
# Create a container without [Moby][moby-dock]

## Before we start
This article is derived from [a great sharing](https://youtu.be/sK5i-N34im8) regarding the underlying secrets of the container world by [Jérôme](https://github.com/jpetazzo) many years ago.

In this article, we'll go through the demo Jérôme did at the end of that sharing.

Many thanks to Mr. Jérôme Petazzoni.

## Environment Requirements
* A running linux host with kernel header version 5.10+.
  * [btrfs][btrfs-git-link] is a tool to create [COW][cow-storage] file systems. Since it's been [deprecated][btrfs-deprecation] from RHEL, the easy yum-install life is not easy anymore. If you want to install it via the source code, kernel heder version 5.10+ is required, and I believe that having your kernel version matches with the kernel header version is a good idea (maybe not, I don't know).
  * The linux host I picked is from [aws lightsail][aws-lightsail-link] with 4 GB memory, and linux distribution is the [CentOS][centos-link] (seems like RedHat heavily involved in the CNCF timeline we live in, so I picked CentOS).
  * Upgrading the linux kernel is very easy. (All 100+ opened tabs on my web browser agreed with me unanimously) (just kidding, 99+ at most)

* [btrfs][btrfs-git-link]. If you decide to install it via the source code, make sure to follow the `INSTALL` markdown file strictly.
* [skopeo][skopeo-git] and [umoci][umoci-git]. `skopeo` is for image retrieval, coverting (from, and to [OCI][oci-webpage] image foramt). `umoci` is for image tarball unpacking. Without having a docker daemon running in our system, these two tools are our perfect alternatives.

* An extra storage for the COW filesystem. I don't want to re-partition the host storage and attached an extra storage to the host. Storage formatting and mounting tutorial can be found [here][btrfs-foramt-mount]

* Last but not least, some useful commands can help you observe the entire lifecycle of the namespaces.
  * `lsns` can list all the namespaces with thier init PIDs
  * `nsenter` allows you to jump into different namespaces.

## Step by Step Breakdown
1. `mount --make-rprivate /`
   > In short, this line will prevent our container file system from bleeding out.

   > In depth, this is about [mount propagation][mount-propagation]. According to this [answer][rprivate-implication], mount propagation is default off for the kernel, but `systemd` automatically remounts all mount points as **MS_SHARED** on system startup so that `nspawn` and the container tools work out of the box. We turn it back off for our convenience. This change will be lost upon reboot.

   PS. The code mentioned in that answer is moved to [here][systemd-mount-setup].

   Now, move to your btrfs mountpoint. In this demo, it's `/btrfs-data/`
2. `mkdir -p images containers oci-images unpacked-images`
   > `skopeo` will retrive a docker image (`alpine` in this demo), convert & save it as oci format to the `oci-images` directory.
   > `umoci` will upack the oci image tarballs into `unpacked-images` directory. Then we will copy the `rootfs` of our unpacked image into `images` directory. As a result, the `images` directory actullay stores the flattened `rootfs` a container engine should see while starting a container.

3. `skopeo copy docker://alpine:latest oci:oci-images/alpine:latest`
   > This command will write the alpine image in oci format to the `oci-images` directory.
   > ![](assets/skopeo-copy-to-oci-image.png)

4. `sudo umoci unpack --image oci-images/alpine unpacked-images/alpine`
   > This command will unpack the oci image into two major parts: the `rootfs` and the `config.json`.
   > `rootfs` will be the fs of your container, and the `config.json` contains all the magic specs your container engine needs to start a container.
   > Since we are the magician that doing the tricks today, the `rootfs` is all we need. But please make sure to take a loot at the `config.json` file, very imformative.
   > ![](assets/umoci-unpack-oci-image.png)

5. `btrfs subvol create images/alpine`
   > [COW][cow-storage] file system is crucial to containers. Jérôme's another [talk][docker-storage-driver-talk] explained it in depth.
   > This command creates a subvolume under `images/alpine`

6. `cp -r unpacked-images/alpine/rootfs/* images/alpine`
   > Copy the `rootfs` to the image directory.

7. `btrfs subvol snapshot images/apline/ containers/tupperware`
   > Crete a snapshot for the image file system.

   > Every single time, when you start a container from an image, you actually create a mutatble snapshot of the image, and use this snapshot as your container's file system.
   > Why?
   > Let's consider a case, for some unkown reasons, you are insanely running 1000 mysql containers on your poor Linux host. Since most of the files in those containers are unchanged throughout the entire container lifecycle, as COW snapshots, no copy happened, and all such unchanged files are still pointing to the same original files in your image. Result? Huge disk space save.
   > On the other hand, even if you are rich enough to buy extra storages just to witness thousands of identical files. Copying those files to your containers still takes time. As a result, you might need to wait for a long time for your container to be ready after exected `docker run` command.
8. `touch containers/tupperware/THIS_IS_TUPPERWAAAARE`
   > Great, we have our own snapshot of the `rootfs`, let's touch it.

9. `chroot containers/tupperware/ sh`
   > Change the root dir to our container's rootfs, have a peek.

10. `ctrl + d` Back to the host fs
    `unshare --mount --uts --ipc --net --pid --fork bash`
    > This command creates new namespaces.
    > **pid** namespace creation is a little bit more complicated than the rest. Make sure to have `--fork` while creating a new **PID** namespace. It ensures that the executed command is performed in a child process that (being the first process in the namespace) has PID 1. Otherwise, you'll see an error message similar to **_fork: Cannot allocate memory_**. [Here][unshare-fork] is a more detailed demonstration.
    > Actually, we missed another flag `--mount-proc` for our **pid** namespace creation, and will need to do it afterwards, the reason why both `--fork` and `--mount-proc` are needed can be found [here][unshare-pid-ns].
    > [Here][unshare-mount-proc-failed] is also another example can help you understand the **pid** userspace creation better.

11. `hostname tupperware`
    > Set up the container's hostname, nothing special.

12.  For example, by running `ps`, you can see only your processes, but the pid is not pid 1. Because you are still in the `/proc` of the system, and having the system view of your namespaced processes. We will fix this later

13. Now, `pivot_root`.
    ```
    cd containers/tupperware.
    mkdir oldroot
    pivot_root . oldroot/
    ```
    > At step 9, we used `chroot` to take a quick look at our container's `rootfs`, but it's not sufficient. The chroot utility only changes the root for the program, (`sh` in our case) from which it is called – all existing processes and programs started from another shell use the original root.
    > On the other hand, The `pivot_root` utility exchanges the current root filesystem with a new root filesystem.
    > > You may encounter an error says **Invalid argument**. According to Jérôme, to make `pivot_root` work properly, you need to have the new root be close to the the top level of the file system. So, following commands will do the job.
    > > `mount --bind /btrfs-data/containers/tupperware/ /btrfs-data/containers/tupperware/`
    > > This command converts your directory into a mount
    > > `mount --move /btrfs-data/containers/ /btrfs-data/`
    > > Move the mount few levels up. Then exec your `pivot_root` command again.

14. `mount -t proc none /proc`
    > mount a proc type pseudo filesystem to your `/proc`
    > This is equivalent to having `--mount-proc` in our `unshare` command above. Now the `ps` command can work properly.

15. `mount` command now can still see the mounts in your host. Use `umount -a` to do the cleanup, the `oldroot` removal is a little bit tricky, `umount -l /oldroot/`. Since the `/proc` is also unmounted, `mount -t proc none /proc` to get it back.

16. Networking. TBD

[moby-dock]: https://www.docker.com/blog/docker-project-announces-open-source-a-thon-to-support-whale-and-marine-wildlife-conservation/
[btrfs-deprecation]: https://news.ycombinator.com/item?id=14907771
[btrfs-git-link]: https://github.com/kdave/btrfs-progs/
[cow-storage]: https://en.wikipedia.org/wiki/Copy-on-write#In_computer_storage
[aws-lightsail-link]: https://aws.amazon.com/lightsail/
[centos-link]: https://www.centos.org/
[skopeo-git]: https://github.com/containers/skopeo
[umoci-git]: https://github.com/opencontainers/umoci
[btrfs-foramt-mount]: https://linuxhint.com/create-mount-btrfs-subvolumes/
[oci-webpage]: https://opencontainers.org/
[mount-propagation]: https://medium.com/kokster/kubernetes-mount-propagation-5306c36a4a2d
[rprivate-implication]: https://serverfault.com/questions/868682/implications-of-mount-make-private
[systemd-mount-setup]: https://github.com/systemd/systemd/blob/05576809194754989f88f83c7104341c35944546/src/shared/mount-setup.c#L528
[docker-storage-driver-talk]: https://youtu.be/9oh_M11-foU
[unshare-fork]: https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory
[unshare-pid-ns]: https://unix.stackexchange.com/questions/535528/why-unshare-p-does-not-imply-f-and-mount-proc
[unshare-mount-proc-failed]: https://bugzilla.redhat.com/show_bug.cgi?id=1390057

branch_name: refs/heads/main


text:
---
date: 2022-09-15
title: 5 ways of helping your dyslexic child
categories:
  - mitigations
author_staff_member: adam
published: true
---
Dyslexia is a learning disability that affects reading ability. It's a common condition, affecting
about 5% of the population. Dyslexia can make it difficult for a person to read quickly and
accurately. Some kids also have trouble sounding out words. But dyslexia isn't caused by low
intelligence or a lack of motivation. Although dyslexia isn't a curable condition, there are
ways of helping your child. Keep reading to find out more.

![Reading child](/images/girl-in-pink-shirt-reading.jpg)

Photo by Jonathan Borba on Unsplash

1. ### Find out what dyslexia is.
There are many misconceptions about what dyslexia is and what
it isn't. Sometimes people think that dyslexia is caused by poor parenting or by the child's
teacher. In reality, it's a condition that has nothing to do with IQ. Dyslexia is a learning
disability that can affect reading, writing, spelling, and speech. It can also affect other
aspects of life, such as concentration and organization skills. Experts believe that most cases
of dyslexia are caused by problems in specific areas of the brain. However, the cause of
dyslexia is unknown.
2. ###  Get help for dyslexia.
If your child has trouble reading and writing, talk to their teacher
about getting extra help.  They can teach them different ways to learn and
how to compensate for their weaknesses. They also can teach special strategies that can
help them read more effectively. You can also hire a professional who specializes in learning
disabilities to help your child. Sometimes a tutor who has experience working with children
who have dyslexia can help a lot.
3. ### Treat the "big" problems first.
Most cases of dyslexia involve trouble with reading fluency
and comprehension. Your child may have trouble identifying words and understanding what
they have just read. They may also have difficulty using context clues to figure out the
meaning of a sentence. Your child can also have trouble writing because of poor spelling,
punctuation, and capitalization.
4. ### Consider using technical tools.
If your child is having trouble reading, there are a number
of technological tools that can help. For example, you can get a program that reads text out
loud for your child. There are also programs that teach your child how to sound out words.
5. ### Boost your child's confidence.
Teach your child about dyslexia, and explain that it is just a
"learning difference". Help them understand that dyslexia does not define who they are.

Now you have hopefully been inspired to consider getting your child some support. It is
tough, but know that you are not alone and there are strategies that you can use. I hope this
blog post has given you some insight and ideas that may help you and your child!

gha_language: HTML


text:
# Job with children

todo

```php
<?php

declare(strict_types=1);

use Yokai\Batch\Job\JobExecutor;
use Yokai\Batch\Job\JobInterface;
use Yokai\Batch\Job\JobWithChildJobs;
use Yokai\Batch\JobExecution;
use Yokai\Batch\Registry\JobContainer;
use Yokai\Batch\Registry\JobRegistry;
use Yokai\Batch\Storage\NullJobExecutionStorage;

// you can instead use any psr/container implementation
// @see https://packagist.org/providers/psr/container-implementation
$container = new JobContainer([
    // here are the jobs you will want to write
    // each job has an identifier so it can be launched later
    'export' => new class implements JobInterface {
        public function execute(JobExecution $jobExecution): void
        {
            $exportSince = new DateTimeImmutable($jobExecution->getParameter('since'));
            // your export logic here
        }
    },
    'upload' => new class implements JobInterface {
        public function execute(JobExecution $jobExecution): void
        {
            $pathToUploadExportedFile = $jobExecution->getParameter('path');
            // your upload logic here
        }
    },
]);

$job = new JobWithChildJobs(
    $jobExecutionStorage = new NullJobExecutionStorage(),
    new JobExecutor(new JobRegistry($container), $jobExecutionStorage, null),
    ['export', 'upload']
);
```

repository: yokai-php/batch

gha_language: PHP

repo_name: yokai-php/batch


text:
[![DeepScan grade](https://deepscan.io/api/teams/10012/projects/12697/branches/199343/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=10012&pid=12697&bid=199343)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/ashish-r/whatsapp-direct/blob/master/LICENSE)

# WhatsAppDirect!

An ultra-lite web app that lets you message/call on #WhatsApp without adding the number to your contacts list.

### Visit: https://whatsapp.ashish.link

# Getting Started

Navigate to the root directory and use:

## Installing Dependencies

`npm install` to install all dependencies.

## For Development:

`npm run serve` this will start typescript transpiler in watch mode, any changes you make in the .ts file will automatically update corresponding .js file in the assets directory

`npm run serve-sass` this will start sass in watch mode, any changes you make in the .sass file will automatically update corresponding .css file in the assets directory

## For Production:

`npm run build` this will copy all the required files to the build directory and minifies assets with grunt.

## Git Hooks:

`pre-commit` runs `npm run deploy` which builds the project with `npm run build` and push updates in `gh-pages` branch.

# Screenshots

![PWA Mobile][pwa mobile]
![PWA Update][pwa update]
![PWA Desktop][pwa desktop]
![qrcode desktop][qrcode desktop]

[pwa mobile]: https://github.com/ashish-r/whatsapp-direct/blob/master/screenshots/Screenshot_20191011-042640.jpeg
[pwa update]: https://github.com/ashish-r/whatsapp-direct/blob/master/screenshots/Screenshot_20191011-042616.jpeg
[pwa desktop]: https://github.com/ashish-r/whatsapp-direct/blob/master/screenshots/Screenshot%20from%202019-10-11%2004-24-50.jpeg
[qrcode desktop]: https://github.com/ashish-r/whatsapp-direct/blob/master/screenshots/Screenshot%202020-08-01%20at%2011.00.17%20PM.png

repository: ashish-r/whatsapp-direct

repo_name: ashish-r/whatsapp-direct


text:
---
layout: post
title:  "Better graph loading in Entity Framework"
excerpt: "This article is for those who want to go further with Entity Framework and those who think Entity Framework and ORMs, in general, are slow."
date:   2012-03-01 22:18:44
categories: post
tags : [EF, Entity Framework]
lang : [en]
image:
  feature: abstract-11.jpg
---

This article is for those who want to go further with Entity Framework and those who think Entity Framework and ORMs, in general, are slow.

#Context

Let's start to see how efficiently load a multi levels graph of objects from the database.

#Models

First, we create our model's classes : Subject, Category, SubCategory.

Subject is an heavy object that has multiples categories and a Category can have multiple SubCategory.

```csharp
public class ArticleDownloadedHandler : IHandleEvent<ArticleDownloaded>
{
    private readonly IReadabilityService _readabilityService;
    private readonly IArticleRepository _articleRepository;

    public ArticleDownloadedHandler(IReadabilityService readabilityService,
        IArticleRepository articleRepository)
    {
        _readabilityService = readabilityService;
        _articleRepository = articleRepository;
    }

    public async Task HandleAsync(ArticleDownloaded domainEvent)
    {
        var article = await _readabilityService.GetArticleAsync(domainEvent.ArticleId);
        article.Row.TypedId = domainEvent.LocalId;
        article.Row.DownloadedAt = domainEvent.Date;
        _articleRepository.Persist(article.Row);
    }
}

public class Category
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual int SubjectId { get; set; }
    public virtual Subject Subject { get; set; }
    public virtual ICollection<SubCategory> SubCategories { get; set; }
}

public class SubCategory
{
    public virtual int Id { get; set; }
    public virtual int Name { get; set; }
    public virtual int CategoryId { get; set; }
    public virtual Category Category { get; set; }
}

public class GraphContext : DbContext
{
    public GraphContext()
    {
        Configuration.LazyLoadingEnabled = true;
        Configuration.ProxyCreationEnabled = true;
    }

    public DbSet<Subject> Subjects { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<SubCategory> SubCategories { get; set; }
}
```

#The target
I want to load one (or multiples) subject(s) with all its categories and sub categories.
Here, we have an one-to-many relation between Subject and Category and another one-to-many relation between Category and SubCategory.

- Get all the graph in one shot with the "Include" method.

##Lazy loading

The lazy loading is activated when you naturaly navigate into reference properties and collections.

```csharp
static void Lazy()
{
    using (var context = new GraphContext())
    {
        var subjects = context.Subjects.Take(fetchSize).ToList();
        foreach (var subject in subjects)
        {
            foreach (var category in subject.Categories)
            {
                foreach (var subCategory in category.SubCategories)
                {
                }
            }
        }
    }
}
```

So what's happenning here ? In the first case you have:

- One query to load the Subject object(s),
- One query per subject to load the categories associated,

- One query per categories to load the sub categories associated.

This is the **n+1 loading problem** and as you can see that it's not an efficient way to load data.

##Include

The include technique allow you to fetch relational data in one shot, reducing the number of trips to the database.

```csharp
static void Include()
{
    using (var context = new GraphContext())
    {
        var subjects =  context.Subjects
            .Include("Categories.SubCategories")
            .Take(fetchSize).ToList();
    }
}
```

Unfortunatly in this case the loading time with Include is far superior to the standard lazy-loading technique !

How is it possible ?
In fact the Include method create a **sql left outer join**. So if we have a subject with 30 categories that each have 20 sub categories the result set of the query contains 1 * 30 * 20 = 600 times the subject data ! If the subject data is big, your result set will be 600 bigger than it should be.

This is why, in my own opinion, the include pattern is, sometimes, an anti-pattern.
Indeed it should be use only on many-to-one relations (that avoid this type of joins) or when the lisibility of the code is more important than the performances.

#Alternative

So how can I efficiently load my objects ?

My technique is to query once per levels and then link the objects in your application.

This technique is automatic (lazy) in others ORM like NHibernate and named as the **batch loading** but in Entity Framework you have to do it manualy.

Let see how it can be written:
(Note that I deactivate the lazy-loading because of the lines that cast to EntityCollection. You don't need to do this if you use EntityObject for your models)

```csharp
static void MultiQuery()
{
    using (var context = new GraphContext())
    {
        context.Configuration.LazyLoadingEnabled = false;
        var subjects = context.Subjects.Take(fetchSize).ToList();
        var subjectsIds = subjects.Select(s => s.Id).ToArray();

        var categories = context.Categories
                .Where(c => subjectsIds.Contains(c.Subject.Id))
                .ToList();

        var categorieIds = categories.Select(s => s.Id).ToArray();

        var subCategories = context.SubCategories
            .Where(c => categorieIds.Contains(c.Category.Id))
            .ToList();

        var categoriesDict = categories.GroupBy(c => c.Subject.Id)
            .ToDictionary(c => c.Key, c => c.ToList());
        var subCategoriesDict = subCategories.GroupBy(c => c.Category.Id)
            .ToDictionary(c => c.Key, c => c.ToList());

        foreach (var subject in subjects)
        {
            var categoriesCollection =
                (EntityCollection<Category>)subject.Categories;
            categoriesCollection.Attach(categoriesDict[subject.Id]);
        }

        foreach (var category in categories)
        {
            var subCategoriesCollection =
                (EntityCollection<SubCategory>)category.SubCategories;
            subCategoriesCollection.Attach(
                subCategoriesDict[category.Id]);
        }
        context.Configuration.LazyLoadingEnabled = true;
    }
}
```

Wow, what's a huge code !  Yeah that's a lot of code for loading an object.
But now let see the results in a benchmark with one and multiples subjects:

![Benchmark][benchmarkEfImage]

In this case we have an improvement in performance from 8 to 15 times relativily to the include pattern!

Ok but you can imagine that I optimised the data for this demonstration but don't forget this:

- My database is local and one of biggest problem is the volume of data loaded by the Include pattern.
- I have only one concurent access, imagine if I multiply the same access parallelly? Your data transfert (mostly on network) will be saturated.
- In real world application, I personaly applied this technique several times and won performances from 3 to 8 times vs Include or lazy loading.

Indeed, in this kind of scenario the most efficient way to load data is a multi result set stored procedure.

You can find the source code associated to this article [here][github-link]

If you try and you have any observations do not hesitate to comment. ;-)

[benchmarkEfImage]: /images/article/objects-graph-loading-in-entity-framework/graphloading.png
[github-link]: https://github.com/anthyme/EfGraphLoading

repository: anthyme/hpstr-jekyll-theme

repo_name: anthyme/hpstr-jekyll-theme


text:
# Visma.net token creator #

Have Visma.net create a token for you and send it by email. This way you can send your clients a link and get a token with a list of context by email.

If you want to create a copy of this service you can fork this repository, create a new Azure Functions App and set it to deploy from Github. Set the Application Settings as described below.

[![Deploy to Azure](https://azuredeploy.net/deploybutton.svg)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FON-IT%2FVismaNetTokenGenerator%2Fmaster%2Fazuredeploy.json)

## Application settings

You'll have to set these application settings as soon as you've installed the app in Azure.

| AppSetting | Description |
| ---------- | ------------ |
| VismaNetClientId | The client Id provided by Visma |
| VismaNetClientSecret | The client secret provided by Visma |
| VismaNetCallbackUrl | The url to https://[your-app-name].azurewebsites.net/api/callback |
| AzureWebJobsSendGridApiKey | API key from Sendgrid.com (It's a free service for 12k emails a month) |
| SendGridFrom | Who the email should be sent from |
| SendGridTo | Who should receive the email |
| SendGridSubject | Subject for the email |

repository: ON-IT/VismaNetTokenGenerator

gha_language: C#

repo_name: ON-IT/VismaNetTokenGenerator


text:
# Button

A basic `<Button />` component without any visual effects on user interaction. For buttons with visual effects use
the `ActionButton` and `RippleButton` components.

## Getting started

```
import Button from 'Template/components';

...

<Button type="primary">My button</Button>
```

## Props

See the documentation of the library `Button` component for inherited properties. Additionally, this component
provides the following properties:

### type

_Type_: `string`
_Default_: `primary`

The color scheme of the button, may be one of the following:
`primary`, `secondary` or `regular`.

`primary` and `secondary` will render the button in the primary/secondary color palette as defined in
the button styles. These settings allow the rendering of flat buttons by setting the `flat` property (see below).

`regular` will always render a flat button with a dark color.

### flat

_Type_: `boolean`
_Default_: `false`

If set, the button will be rendered flat, without any background color set and using the color schemes primary color
as text color.

### wrapContent

_Type_: `boolean`
_Default_: `true`

If this prop is set, the content will get wrapped inside a padded element when rendererd. This is useful for
text and centered content and should be disabled if the content should span over the full size of the button.


text:
# pallet.js
Javascript canvas abstraction layer for drawing shapes and simple objects.

Usage
-----

Clone pallet.js with git:

```bash
git clone git://github.com/Asraelite/pallet.js.git
```

Include it in your project:

```html
<script src="pallet.js"></script>
```

Create a new __Pallet__ object, passing the id of the canvas element you want to use:
```javascript
var pallet = new Pallet('#mycanvas');
```

You can also pass a canvas element directly, or exclude the "#" in the id. If you do not pass anything, Pallet.js will look for the first canvas element in the document and use that.

You may then call the functions of the pallet object to draw different things to the canvas.

To draw a rectangle:

```javascript
pallet.rect(color, x, y, width, height);

// Example:
pallet.rect('#f00', 50, 90, 20, 15);
```

To draw a circle:
```javascript
pallet.circle(color, x, y, radius);

// Example:
pallet.circle('#aa8', 150, 150, 50);
```

To clear the canvas:

```javascript
pallet.clear();
```

To clear a section of the canvas:

```javascript
pallet.clear(x, y, width, height);

// Example:
pallet.clear(200, 200, 500, 100);
```


text:
# Artifact Hub

[![CI](https://github.com/artifacthub/hub/workflows/CI/badge.svg)](https://github.com/artifacthub/hub/actions?query=workflow%3ACI)
[![Go Report Card](https://goreportcard.com/badge/github.com/artifacthub/hub)](https://goreportcard.com/report/github.com/artifacthub/hub)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/4106/badge)](https://bestpractices.coreinfrastructure.org/projects/4106)
[![Artifact HUB](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/artifact-hub)](https://artifacthub.io/packages/helm/artifact-hub/artifact-hub)
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/artifacthub/hub)

Artifact Hub is a web-based application that enables finding, installing, and publishing packages and configurations for CNCF projects. For example, this could include Helm charts and plugins, Falco configurations, Open Policy Agent (OPA) policies, OLM operators, Tinkerbell actions, kubectl plugins, Tekton tasks, KEDA scalers and CoreDNS plugins.

Discovering artifacts to use with CNCF projects can be difficult. If every CNCF project that needs to share artifacts creates its own Hub this creates a fair amount of repeat work for each project and a fractured experience for those trying to find the artifacts to consume. The Artifact Hub attempts to solve that by providing a single experience for consumers that any CNCF project can leverage.

The project, accessible at [https://artifacthub.io](https://artifacthub.io), is currently in development in a beta state. Support for Helm charts and plugins, Falco configurations, OPA policies, OLM operators, Tinkerbell actions, kubectl plugins, Tekton tasks, KEDA scalers and CoreDNS plugins is in development with plans to support more projects to follow. Pull requests, especially those to support other CNCF projects, are welcome. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) and [dev.md](./docs/dev.md) for more details.

Feel free to ask any questions on the #artifact-hub channel in the CNCF Slack. To get an invite please visit [http://slack.cncf.io/](http://slack.cncf.io/).

## Getting started

Artifact Hub allows publishers to list their content in an automated way. Please check out the [repositories guide](./docs/repositories.md) for more details about how to add your repositories.

If you want to run your own Artifact Hub instance in your Kubernetes cluster, the easiest way is by deploying the Helm chart provided. For more details, please see the [Helm chart README file](charts/artifact-hub/README.md).

## Community

The Artifact Hub is an open source project. Aside from contributing code and feature suggestions you can also engage via:

- Attending a meeting. Meetings are on the 2nd Tuesday of the month at 10:30am PT / 1:30pm ET. [Meeting minutes and agenda are in Google Docs](https://docs.google.com/document/d/1nkIgFh4dNPawoDD_9fV7vicVSeKk2Zcdd0C5yovSiKQ/edit).
- Joining [CNCF slack](https://cloud-native.slack.com) ([join link](https://slack.cncf.io/)) and joining the room #artifact-hub.

## Process

Artifact Hub is a [CNCF Sandbox Project](https://www.cncf.io/sandbox-projects/).

We're envisioning that Artifact Hub will have three main components:

1. The software, consisting of frontend code using React, backend written in Go, and Postgres with a number of stored procedures
2. A process by which new artifacts get added to Artifact Hub, updated, and removed. The documentation for this process is just beginning, but it needs to be publicly documented, transparent, and robust. In particular, edge cases need to be able to be reviewed by the project maintainers, with an appeal path to SIG Apps and the TOC
3. Operational responsibilities. A number of organizations are likely to depend on Artifact Hub not to “break the build” and so the maintainers will need to provide a high level of uptime, with CNCF funding the hosting and related systems

## Code of Conduct

This project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

## Security

To report a security problem in Artifact Hub, please contact the Maintainers Team at
<EMAIL_ADDRESS>Please see [SECURITY.md](./SECURITY.md) for more details.

## License

Artifact Hub is an Open Source project licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).


text:
channels-chat
=============

Demonstration of a WebSockets-based chat server, utilizing:

* `Django Channels <http://channels.readthedocs.io/>`_
* `React <https://facebook.github.io/react/>`_ and `Redux <http://redux.js.org/>`_
  for a reactive client-side application
* Redis as a scalable backend

How it works
------------

A React / Redux frontend application written in ES6, communicates via a
Websocket connection to a Python-based ASGI server. The frontend sends
Redux-style actions as JSON via the Websocket connection, such as
``"{'type': 'LOGIN_USER', 'username': 'joe'}"``. As implemented by `Django Channels
<http://channels.readthedocs.io/en/latest/concepts.html>`_, the ASGI Interface
Server handles the Websocket connection, passing the message onto a Redis queue
for any available Worker to consume the message.  The consumers will use the
Redux-style action to delegate to the appropriate ``chat.engine.ChatEngine``
method (e.g. ``LOGIN_USER``, ``REQUEST_MESSAGES``).  The ``ChatEngine`` method
typically will perform some database action (lookup user / messages, store
message) and respond to ``send`` a response back to one or more Channels,
which the Interface server will read back from Redis and communicate back to
the client via the open Websocket connection.  The ``ChatEngine`` currently
can send to three types of Channels:

1) "Room channels", a ``channels.Group`` representing an ``chat.models.Room``,
   in which all clients that are part of that room will receive the message.
2) The "control channel", a ``channels.Group`` representing all open
   socket connections for a specific ``chat.models.User``.
3) The "reply channel", the specific channel for the current websocket
   connection.

Supported Actions
-----------------

channel_chat is a functional MVP to test out websockets, Channels, and React,
but lacks several key items necessary to make it a production-ready chat
application (see TODO).  The currently supported actions are:

* Connect - Client connection is immediately upgraded from HTTP to Websocket
* Login - User enters handle, ``LOGIN_USER`` sent to server. Server responds with
  ``LOGIN_SUCCESS`` (see TODO below) and list of rooms (``RECEIVE_ROOMS``),
  pre-building the all the "room channels".
* Send Message - The user can select a Room, enter text and issue a
  ``SEND_MESSAGE`` to the server. The server will store the
  ``chat.models.Message``, then broadcast that message back out to the entire
  "room channel" via the ``RECEIVE_MESSAGES`` action.  Clients, upon receiving
  the ``RECEIVE_MESSAGES`` action, will update it's Redux state and, if in the
  room receiving he message, reactively re-render the ``<MessageList />``.
  This "room channel" abstraction means that all active websockets will receive
  the broadcast, even if the same user is logged in from multiple devices.
* Clients can request message history via ``REQUEST_MESSAGES``, which is
  returned via the "reply channel". Several events trigger a message request:

  * When changing rooms, a room ID is passed, and the last 50 messages are sent
    (see TODO)
  * If the client disconnects and the ``ReconnectingWebsocket`` is able to
    reconnect, on reconnect, all messages since the `last message` are requested
    and returned.
  * When scrolling back into the room's history, the client will request
    messages earlier than the first message for that room (see TODO for better
    infinite scroll).

TODO
----

* Real authentication and then migrate the HTTP session into the Channel session
  as part of ``ws_connect``.
* Multi-user rooms. Abstraction already in place for 1 Room to Many Users.
  Need to ensure controls around who can send to which Rooms.
* "Add Contact" functionality. Currently we inefficiently pre-create 1-1 rooms
  for every user pair.
* Implement Active / Inactive status flag to show who is online (track via
  Control-group ping after User hits ``ws_disconnect``).
* Implement an unread message count next to the ``<Room />``.
* Avoid re-requesting messages for a room when switching between rooms.
* Implement intelligent "infinite scroll" when scrolling back on a room's
  history. Basic onScroll has been implemented, but should trigger prior to
  ``scrollTop == 0``, should display a loading indicator, and should stay pinned
  to location of current messages in view.
* Better workflow for initial post-login (e.g. user's last open room).
* Implement `@handle` parsing and linking.
* Implement the Notification Browser API to provide OS-level alerts on new
  messages.
* Provide message search.

Running
--------

The system has been tested with Ubuntu 14.04, node.js 6.0.3, Python 3.4::

  git clone https://github.com/SeniorDev34/Django_React_Chat
  cd channel_chat

Add :file:`project/local_settings.py`, with a ``SECRET_KEY`` and optionally
``DEBUG``::

  SECRET_KEY = 'mysecret'
  DEBUG = True

Continue::

  nvm use 6  # assumes using nvm to install node.js 6
  make env
  make static
  make createdb
  make migrate
  make serve

To run the test suites (mocha and Python unittest)::

  make test


text:
# MND-DEV

Command line interface with install, update and quality of life functionality
for all platform related mynewsdesk repos.

## Install

The [dev computer](https://github.com/mynewsdesk/dev-computer/) script installs
it for you but if you need to do it manually simply run:

```bash
brew install --HEAD mynewsdesk/tap/mnd
```

## Configuration

Run `mnd setup` to configure where you want to install the repos etc. All settings
will be stored in YAML format in `~/.mnd`.

After running setup you can install all the Mynewsdesk repos with `mnd install`. If you prefer to install only specific repositories you can run `mnd list` to get a list of all repos and then `mnd install <repo-name>` to install them one by one.

Please have a look at the Usage section below to get familiar with all available commands (`mnd deploy` is pretty great, for example).

## Update

To update to the latest version simply run `mnd update`.

## Usage

Check the usage by typing `mnd help`

```
Usage: mnd COMMAND [repo1 repo2] [command-specific-options]

Type 'mnd help COMMAND' for details of each command

Available commands:
deploy          Deploy app to a server
edit            Open repo source in editor
help            Helps you out!
install         Install missing repos
list            List all repos
logs            Tail logs
open            Conveniently opens services based on repository context
platform        Get or set the current platform
run             Run shell commands on multi-repos
setup           Configures the mnd tool
update          Self update
upgrade         Upgrade all or given repos
```

Check detail usage for one command `mnd help logs`:

```
Tail logs

Usage:
  mnd logs # tail all logs
  mnd logs mynewsdesk media_monitor # tail logs from mynewsdesk and media_monitor

  Note: tails log/development.log where available
```

## Development setup

Clone the repo and run `bin/setup`

Run `crystal build ./src/mnd.cr -o bin/mnd` to build the executable.

Executable will be available as `bin/mnd` which you can run to test your
changes before publishing.

If you are getting the `library not found for -lssl` error when attempting to compile please patch your `LIBRARY_PATH` as explained in: https://github.com/brianmario/mysql2/issues/795#issuecomment-337006164

### Publish a new release

Just merge your changes to master. Running `mnd update` will reinstall using the current HEAD.

### Add a repo

Add repos to the various platforms in `src/mnd/platforms.cr`.

### Add command

Create a new command class in the `src/mnd/commands` directory:

```ruby
module Mnd
  class Commands::Awesome < Commands::Base
    # The summary is one short sentence, which will appear in the help page
    # The usage is the details, which will appear when running 'mnd help awesome'
    summary "An awesome command"
    usage <<-EOF
    mnd awesome # show how awesome it is
    EOF

    # The command executes via the perform method
    def perform
      # Use display.[info|warn|error|debug] to display text on screen
      display.info "This is an awesome command!"
    end
  end
end
```

### Useful methods in the `Mnd::Commands::Base`

`Base#selected_repos`

Get currently selected repos based on command line arguments.

For example when running, `mnd logs mynewsdesk audience` then the `selected_repos`
will be `["mynewsdesk", "audience"]`.

However if no apps are specified it returns an empty array so when running
`mnd logs` the `selected_repos` will be `[]`. You might want to either display
an error (`return display.error "No repo specified if selected_repos.empty?"`) or
default to use all apps (`selected_repos.presence || Repo.all`) in that case.

`Base#display`

Use `display` to get a display to print message instead of puts everywhere.
It supports color in terminal. By default:

* display.info: default color
* display.error: red
* display.warn: yellow
* display.debug: light_black

`Base#run(cmd, repo = nil)`

Use it to run external command.

Parameters:

* cmd, String of the command you want to run
* repo, Optional if you want to run cmd on an repo

When repo is passed, it will cd to the root of repo then run the command.

repository: mynewsdesk/mnd-dev

gha_language: Crystal

repo_name: mynewsdesk/mnd-dev


text:
# Firebase Token Reporter

Firebase Token Reporter is utility class which enables integration with Firebase Cloud Messaging (FCM).
It's based on Instance ID Server API
[documented in full here](https://developers.google.com/instance-id/reference/server#create_registration_tokens_for_apns_tokens).

The purpose of this class is to be used in iOS app which does not directly work with Firebase; instead it connects with its own backend web API which uses Firebase for push notifications delivery.

This is often the case when iOS app client is added for a service already using Android / web front-ends.

Ideally, this would not be needed and iOS app would deliver APNS token to its backend web API, which will then make server to server call to convert APNS token with FCM token. When that‘s not available (for whatever reason) then this is your only option apart from integrating Firebase/Core through CocoaPods. Which I never want to do since the damn thing is – out of the box – one of the most invasive 3rd party libraries I have seen.

## APNS / FCM Configuration

Your app should already be configured completely in Firebase Console / Settings / Cloud Messaging. In particular, you need to:

* create APNS Auth Key in Apple’s Developer Portal
* upload it to FCM Console and
* setup other details for the app there

See the [overview of required steps](https://firebase.google.com/docs/cloud-messaging/ios/certs) in Firebase documentation for more details.

## Usage

Either in AppDelegate or anywhere you deem right – configure the singleton with the FCM server key and the APNS environment you are using.

```swift
private lazy var firebaseTokenReporter: FirebaseTokenReporter = {
	let ftr = FirebaseTokenReporter.shared
	if
		let serverKey = FirebaseTokenReporter.serverKey,
		let environment = FirebaseTokenReporter.activeEnvironment
	{
		ftr.configure(with: serverKey, for: environment)
	}
	return ftr
}()
```

Later, when you receive the token from APNS in AppDelegate, you call the only method there is:

```swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
	let tokenParts = deviceToken.map { data -> String in
		return String(format: "%02.2hhx", data)
	}
	let token = tokenParts.joined()
	log(level: .info, "Received APNS DeviceToken: \( token )")

	firebaseTokenReporter.register(deviceToken: token, onQueue: .main) {
		[unowned self] fcmToken, firebaseError in

		if let firebaseError = firebaseError {
			self.log(level: .warning, firebaseError)
			return
		}

		self.fcmToken = fcmToken
		self.log(level: .info, "Received FCM token: \( fcmToken ?? "" )")
	}
}
```

Now you have FCM token and you can send it to your app’s service backend.

repository: radianttap/FirebaseTokenReporter

repo_name: radianttap/FirebaseTokenReporter


text:
---
layout: default
---

# 1997-10-11 - IETF policy on refusing to allow politics to weaken protocols (Re: Why Adam Back keeps politicizing technical issues)

## Header Data

From: Adam Back<EMAIL_ADDRESS>To<EMAIL_ADDRESS>Message Hash: b00be1b9325c526938f5f940e3d3462ac0a584e2e45ee043500c5dc6346db963

Message ID<EMAIL_ADDRESS>Reply To<EMAIL_ADDRESS>UTC Datetime: 1997-10-11 10:34:59 UTC

Raw Date: Sat, 11 Oct 1997 18:34:59 +0800

## Raw message

```
{% raw  %}From: Adam Back<EMAIL_ADDRESS>Date: Sat, 11 Oct 1997 18:34:59 +0800
To<EMAIL_ADDRESS>Subject: IETF policy on refusing to allow politics to weaken protocols (Re: Why Adam Back keeps politicizing technical issues)
In-Reply-To<EMAIL_ADDRESS>Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

Williams title being: `Why Adam Back keeps politicizing technical
issues'

I would like to comment that the reason politics are arising in
discussion of communications security issues is a natural consequence
of the fact that it's a damn political topic.  Ignore the politics and
you may implement a mandatory GAK system, or at least a GAK compliant
one.  Actually I also argue that there are technical security reasons
why the CMR approach offers weaker security.  I've gone over these
reasons already in this thread, so I won't repeat them.

IETF I think has a stated policy (at least this is the case for the
IPSEC standardisation discussions I have been intermittently
following) to not allow politics to weaken it's protocols and
algorithm choices.  PGP Inc introducing GAK compliance at the cost of
security is a clear case where this policy should be kicking in.

William Geiger<EMAIL_ADDRESS>writes:
> In<EMAIL_ADDRESS>on 10/10/97
>    at 08, Adam Back<EMAIL_ADDRESS>said:
>
> Ok Adam here is a challenge for you:
>
> -- Explain why Corporations do not have the right to access *their*
> documents in whatever form they may be in.

You will note that I didn't say this.  In fact I spent half of last
night detailing alternate less GAK friendly ways for PGP Inc to
provide corporate message snooping, the very functionality which is
the motivation for their CMR.  Perhas you were not reading.

What I did say, and it appears to be a meme which didn't stick with
you as I'm sure I raised this in a previous post replying to you is:

Key functionality should be separated: in the same way that you have
separate signature and encryption keys, because of the differences
between appropriate backup policies, security implications, and
life-times, you should have separate email receipt encryption keys and
storage keys.  Transient email receipt keys should not be escrowed,
but for security reasons perhaps should even be securely wiped after
use.

As an additional security bonus: storage keys can be symmetric (where
they are for your own use) which avoids the more less certain and
more quickly sliding target of public key lengths.

I will guess that the reason this meme doesn't suit you is that it's
not the way your OS/2 pgp mail client plugins work, and therefore not
yet part of your mindset.  So perhaps it's not the status quo for your
and some other apps to use separate storage keys for archiving and
receiving encrypted mail; but there are clear security advantages to
doing it this way.

> -- Failing that explain how PGP 5.5 furthers the cause of GAK and
> PGP 2.6.x does not when I can get my network to do the same thing in
> a weekend and a couple of scripts using PGP 2.6.x.

There is are some clear differences:

1. You can visually see multiple crypto recipients in most PGP enabled
MUAs, as they usually correspond to email CC fields.

2. PGP Inc is attempting to weakly enforce this special purpose
message snooping recipient embedded into the key certificate.

3. PGP Inc even has (less clear on details here) I think from Jon
Callas first post: pgp 5.5 client which enforces inclusion on sent
mail as controlled by a remote company message snooping czar &
enforced inclusion on received mail by the SMTP policy enforcer.

4. There is a difference between what you or I may knock up in
scripts, and what PGP Inc attempts to persuade the IETF include as
conformancy requirements, and what PGP does implement ahead of the
standardisation process.

5. The IETF process should be accepting proposed designs and deciding
on the best ones, which PGP Inc, and the other suppliers would then go
and implement.  As it is now, as William Allen Simpson just pointed
out, PGP Inc is cruising ahead implementing, and deploying things
without bothering with the OpenPGP process.

Your point about using normal multiple recipient to provide snooping
is a good one.  It would be a much less GAK friendly solution for PGP
Inc to encrypt to a second recipient without any message snooping
flags encoded into the PGP standard.  That way email clients won't
reply to this second recipient, and users won't have an automated
snooping feature embeded in their PGP for personal privacy, or
competitor re-write of the same compliant OpenPGP app, for someone
else's benefit (recipient company, or government).

To snoop received email, it provides similar amounts of snooping
enforcement if the recipient's PGP 5.5 for business client when the
user decrypts re-encrypts to a storage key that the company does have
escrowed, or where there is a second crypto recipient in the storage.
(Talking mail folders here.)

> -- Failing that explain why there were no great outcries that PGP
> 2.6.x is GAKware???

See above.  The objectionable new feature in PGP5.5 (and apparently
pgp5.0 too without our realisation to this point) is enforcement in
senders clients to support message snooping, in a form which can
easily be used to interoperate with GAK, and thereby prepares
everyones OpenPGP compliant email client to enforce GAK against them.

At the very most the maximum acknowledgement that it seems reasonable
to me for OpenPGP to have of the GAK compliancy feature is to flag
this key and allow the user to send to this recipient at their option.

In addition I am arguing that PGP Inc are doing the Internet community
a major disservice by choosing to implement message snooping in this
way.  Much better, less controversial, and more secure to do the
snooping in the pgp5.5 client after decryption.  That doesn't need to
involve changes to the message spec.  PGP Inc's SMTP policy enforcer
could then be changed in functionality to stripping off the company
snooping crypto recipient field before it leaves the LAN for security
reasons.

> Now if you agree that Corporations *do* have a right to access their
> documents but you disagree with the technical aspects of how PGP 5.5
> achieves this then drop the fearmongering and spell out how you
> think this can be better achieved.

I already did this half a dozen times.  I'm not fear mongering, I'm
attempting to point out the dangers of including GAK compliancy.  And
to point out the opportunity to make PGP non-GAK compliant, and
thereby frustrate mandatory GAK proponents.  PGP is trying to discard
this opportunity, when there are clear alternate methods which can be
argued are more secure, better meet PGP's Jon Callas's stated user
requirements, don't support GAK, and don't require modifications to
the standard.

Adam
--
Now officially an EAR violation...
Have *you* exported RSA today? --> http://www.dcs.ex.ac.uk/~aba/rsa/

print pack"C*",split/\D+/,`echo "16iII*o\U@{$/=$z;[(pop,pop,unpack"H*",<>
)]}\EsMsKsN0[lN*1lK[d2%Sa2/d0<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<J]dsJxp"|dc`

{% endraw %}
```

## Thread

+ Return to [October 1997](/archive/1997/10)

+ Return to "[Adam Back <aba@dcs.ex.ac.uk>](/authors/adam_back_aba_at_dcs_ex_ac_uk_)"
+ Return to "[Bill Frantz <frantz@netcom.com>](/authors/bill_frantz_frantz_at_netcom_com_)"
+ Return to "[Jon Callas <jon@pgp.com>](/authors/jon_callas_jon_at_pgp_com_)"
+ Return to "[Ryan Anderson <randerso@ece.eng.wayne.edu>](/authors/ryan_anderson_randerso_at_ece_eng_wayne_edu_)"
+ Return to "["Tony Mione" <mione@boeing.rutgers.edu>](/authors/tony_mione_mione_at_boeing_rutgers_edu_)"
+ Return to "["William H. Geiger III" <whgiii@invweb.net>](/authors/william_h_geiger_iii_whgiii_at_invweb_net_)"

+ 1997-10-10 (Sat, 11 Oct 1997 06:07:04 +0800) - [Why Corporate Message Recovery isn't Key Escrow](/archive/1997/10/81e2d76ed45a01a9b1fd16792843fc8cec33976e80e9419d6bcd8e50ab752eef) - _Jon Callas<EMAIL_ADDRESS>  + 1997-10-11 (Sat, 11 Oct 1997 11:29:14 +0800) - [Why Jon Callas keeps picking nits (Re: Why Corporate Message Recovery isn't Key Escrow)](/archive/1997/10/8924d3300715e9c08d1501180b4a9e58e6f83d7a86a63fd777d78b892d59c152) - _Adam Back<EMAIL_ADDRESS>    + 1997-10-11 (Sat, 11 Oct 1997 12:36:00 +0800) - [Re: Why Adam Back keeps politicizing technical issues (Re: Why Jon Callas keeps picking nits)](/archive/1997/10/52bf5a2ad6dabf7cacaa5c649442f3f46d826af5453b221ea079a484f81225a3) - _"William H. Geiger III"<EMAIL_ADDRESS>      + 1997-10-11 (Sat, 11 Oct 1997 18:34:59 +0800) - IETF policy on refusing to allow politics to weaken protocols (Re: Why Adam Back keeps politicizing technical issues) - _Adam Back<EMAIL_ADDRESS>      + 1997-10-13 (Mon, 13 Oct 1997 14:58:00 +0800) - [Re: IETF policy on refusing to allow politics to weaken protocols(Re: Why Adam Back keeps politicizing technical issues)](/archive/1997/10/f32fe4ef6a07cdd3b9b8cf4327d14882f70aa2e5187865e2ad598cdb177d1663) - _Bill Frantz<EMAIL_ADDRESS>        + 1997-10-13 (Mon, 13 Oct 1997 20:57:13 +0800) - [Re: IETF policy on refusing to allow politics to weaken protocols(Re: Why Adam Back keeps politicizing technical issues)](/archive/1997/10/28307617a29c90feeef8213d24a15b1d12b56e4a87b885c6e6b36fc38fe4184e) - _Adam Back<EMAIL_ADDRESS>          + 1997-10-13 (Mon, 13 Oct 1997 23:02:33 +0800) - [Re: IETF policy on refusing to allow politics to weaken protocols (Re: Why Adam Back keeps politicizing technical issues)](/archive/1997/10/39540e451004a5268bdd73de4c24bc9e124cd2c84934b4bc06906e7698f957cc) - _"Tony Mione"<EMAIL_ADDRESS>  + 1997-10-11 (Sun, 12 Oct 1997 05:03:47 +0800) - [Re: Why Jon Callas keeps picking nits (Re: Why Corporate Message Recovery isn't Key Escrow)](/archive/1997/10/324cf6fbd441545d1e53b8a5587cc89722d54258028e1cf93ceb567f4c7b54b1) - _Ryan Anderson<EMAIL_ADDRESS>    + 1997-10-11 (Sun, 12 Oct 1997 07:21:14 +0800) - [the case for separate comms keys](/archive/1997/10/a3c8394dbb2d93b88d5c6f930eca9452adcb684d987179e563a2982f09b602a5) - _Adam Back<EMAIL_ADDRESS>    + 1997-10-12 (Sun, 12 Oct 1997 18:41:26 +0800) - [Re: the case for separate comms keys](/archive/1997/10/cfa491810315647c975b77706f09b130b4d5e534eb30d7a77df07318f29cdd7e) - _Ryan Anderson<EMAIL_ADDRESS>      + 1997-10-12 (Sun, 12 Oct 1997 21:10:34 +0800) - [Re: the case for separate comms keys](/archive/1997/10/238e2d2a3708302b08b458fed84eeb18d5f3fa0f158220fdf8b22005baccfbdc) - _Adam Back<EMAIL_ADDRESS>


text:
# LazyStackTutorial

This repo contains completed solutions for the LazyStack tutorials.
- PetStore -- Visual Studio for Windows
    - Read the PetStore README.md for important setup instructions
- PetStoreCLI -- DotNet CLI
    - Read the PetStoreCLI README.md for important setup instructions
- PetStoreMac -- Visual Studio for Mac
    - Red the PetStoreMac README.md for important setup instructions

repository: InSciCo/LazyStackTutorial

repo_name: InSciCo/LazyStackTutorial


text:
# base16-windows-terminal
This is a repository for the Base16 themes for [Windows Terminal](https://github.com/microsoft/terminal) by using the template architecture outlined in https://github.com/chriskempson/base16.

## The Windows Terminal settings file

Since Windows Terminal uses an array of themes as JSON objects within its settings file, a helper script `Combine-Templates.ps1` that generates said array is included in this repository.

Running this command with a single command line argument pointing to the folder `windows-terminal` with the built themes will generate a file `allthemes.json` in the script home directory. The entire contents of this file can be directly pasted into the `schemes` section of the Windows Terminal settings file to include all generated Base16 themes at once. For convenience, such an output file is also included in this repository although it may not be up-to-date with the very latest Base16 themes.

## Applying a color theme

Set the key `colorScheme` in either your Windows Terminal profile of choice or the defaults section to the theme name, e.g.

```javascript
{
    "$schema": "https://aka.ms/terminal-profiles-schema",
    "defaultProfile": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
    "profiles": {
        "defaults": {
            // Use the Base16 Tomorrow Night theme.
            "colorScheme": "Base16 Tomorrow Night"
        },
        "list": [
            {
                "guid": "{574e775e-4f2a-5b96-ac1e-a2962a402336}",
                "hidden": false,
                "name": "PowerShell",
                "source": "Windows.Terminal.PowershellCore"
            }
        ],
        "schemes": [
            // The themes go here.
        ]
    }
}
```


text:
# Lucky Set-Status

Set the Juju status of the script.

${help_message}

## Usage

`lucky set-status`, by default, will set the status **for the script *and* hook combination that it is run in**. This means that running `lucky set-status` in one script, will not overwrite the satus set by another script. Also, if you set the status in a script that was triggered by one hook, it will not overwrite the status set by the same script in a different hook.

When multiple status are set at the same time, the Juju status will be set to a comma separated list of the statuses. This means that, when multiple scripts are running at the same time, you will not have to worry about their statuses getting overwritten by other scripts that are also trying to set the status.

It is typical in charm scripts do something like this:

```bash
# At the beginning of the script
lucky set-status maintenance "Doing something"

# Do stuff...

# At the end of the script
lucky set-status active
```

This will show that you are "Doing something" while the script is running, and then clear the status at the end of the script.

## Setting the Status Name

When setting the status, you can specify the `--name` or `-n` flag to set a specific name for the status. While this name is not visible anywhere, it allows other scripts to set and override that specific status. This allows you to break out of the "each script sets it own status" design.

For example, if you set a status with the name `global-status` in an `install.sh` script, you can later change that status in another script by specifying its name.

repository: timClicks/lucky

repo_name: timClicks/lucky