text:
#include "BLERoles.h"

#include <algorithm>
#include "CordioBLE.h"
#include "CordioGattServer.h"
#include "source/GattServer.tpp"
#include "mbed.h"
#include "wsf_types.h"
#include "att_api.h"

template class ble::interface::GattServer<ble::vendor::cordio::GattServer>;

namespace ble {
namespace vendor {
namespace cordio {

namespace {

static UUID CCCD_UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG);
static const uint16_t CCCD_SIZE = sizeof(uint16_t);

static const unsigned int READ_PROPERTY =
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ;
static const unsigned int WRITE_PROPERTY =
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE;
static const unsigned int WRITE_WITHOUT_RESPONSE_PROPERTY =
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE;
static const unsigned int SIGNED_WRITE_PROPERTY =
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES;
static const unsigned int NOTIFY_PROPERTY =
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY;
static const unsigned int INDICATE_PROPERTY =
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE;

static const uint8_t WRITABLE_PROPERTIES =
    WRITE_PROPERTY |
    WRITE_WITHOUT_RESPONSE_PROPERTY |
    SIGNED_WRITE_PROPERTY;

static const uint8_t UPDATE_PROPERTIES =
    NOTIFY_PROPERTY |
    INDICATE_PROPERTY;

static const uint16_t CONNECTION_ID_LIMIT = 0x100;

} // end of anonymous namespace

GattServer &GattServer::getInstance()
{
    static GattServer m_instance;
    return m_instance;
}

void GattServer::initialize()
{
#if BLE_FEATURE_SECURITY
    AttsAuthorRegister(atts_auth_cb);
#endif
    add_default_services();
}

void GattServer::add_default_services()
{
    if (!default_services_added) {
        default_services_added = true;
        add_generic_access_service();
        add_generic_attribute_service();
    }
}

ble_error_t GattServer::addService_(GattService &service)
{
    add_default_services();
    // create and fill the service structure
    internal_service_t *att_service = new internal_service_t;
    att_service->attGroup.pNext = NULL;
    att_service->attGroup.readCback = atts_read_cb;
    att_service->attGroup.writeCback = atts_write_cb;

    // Determine the attribute list length
    uint16_t attributes_count = compute_attributes_count(service);

    // Create cordio attribute list
    att_service->attGroup.pAttr =
        (attsAttr_t*) alloc_block(attributes_count * sizeof(attsAttr_t));
    if (att_service->attGroup.pAttr == NULL) {
        delete att_service;
        return BLE_ERROR_BUFFER_OVERFLOW;
    }

    // insert every element in the iterator
    attsAttr_t *attribute_it = att_service->attGroup.pAttr;

    /* Service */
    insert_service_attribute(service, attribute_it);
    att_service->attGroup.startHandle = currentHandle;
    service.setHandle(currentHandle);

    /* Add characteristics to the service */
    for (int i = 0; i < service.getCharacteristicCount(); i++) {
        ble_error_t err = insert_characteristic(
            service.getCharacteristic(i),
            attribute_it
        );
        if (err) {
            // FIXME: proper cleanup of data structure:
            //   - att_service->attGroup.pAttr
            //   - blocks allocated for characteristics value
            // NOTE: those are rightfully released when reset() is called.
            delete att_service;
            return err;
        }
    }
    att_service->attGroup.endHandle = currentHandle;

    // add the service to the list of registered services
    if (registered_service) {
        att_service->next = registered_service;
    } else {
        att_service->next = NULL;
    }

    registered_service = att_service;

    // register services and update cccds
    AttsAddGroup(&att_service->attGroup);
    AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb);
    return BLE_ERROR_NONE;
}

uint16_t GattServer::compute_attributes_count(GattService& service)
{
    // start at 1, one attribute is required for the service itself
    uint16_t attributes_count = 1;
    for (int i = 0; i < service.getCharacteristicCount(); i++) {
        attributes_count += 2;
        GattCharacteristic *p_char = service.getCharacteristic(i);
        attributes_count += p_char->getDescriptorCount();
        if (p_char->getProperties() & UPDATE_PROPERTIES) {
            // add a CCCD
            ++attributes_count;

            // verify that it hasn't been counted twice
            for (size_t j = 0; j < p_char->getDescriptorCount(); ++j) {
                if (p_char->getDescriptor(j)->getUUID() ==
                    UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)
                ) {
                    --attributes_count;
                    break;
                }
            }
        }
    }

    return attributes_count;
}

void GattServer::insert_service_attribute(
    GattService& service,
    attsAttr_t *&attribute_it
) {
    ++currentHandle;
    const UUID& service_uuid = service.getUUID();

    attribute_it->pUuid = attPrimSvcUuid;
    if (service_uuid.shortOrLong() == UUID::UUID_TYPE_LONG) {
        attribute_it->maxLen = UUID::LENGTH_OF_LONG_UUID;
    } else {
        attribute_it->maxLen = sizeof(UUID::ShortUUIDBytes_t);
    }
    attribute_it->pValue = (uint8_t*) alloc_block(attribute_it->maxLen);
    memcpy(attribute_it->pValue, service_uuid.getBaseUUID(), attribute_it->maxLen);
    attribute_it->pLen = &attribute_it->maxLen;
    attribute_it->settings = 0;
    attribute_it->permissions = ATTS_PERMIT_READ;

    ++attribute_it;
}

ble_error_t GattServer::insert_characteristic(
    GattCharacteristic *characteristic,
    attsAttr_t *&attribute_it
) {
    bool valid = is_characteristic_valid(characteristic);
    if (!valid) {
        return BLE_ERROR_INVALID_PARAM;
    }

    uint8_t properties = characteristic->getProperties();

    // Create Characteristic Declaration Attribute
    insert_characteristic_declaration_attribute(characteristic, attribute_it);
    ble_error_t err = insert_characteristic_value_attribute(characteristic, attribute_it);
    if (err) {
        return err;
    }

    // insert descriptors
    bool cccd_created = false;
    for (size_t i = 0; i < characteristic->getDescriptorCount(); i++) {
        err = insert_descriptor(
            characteristic,
            characteristic->getDescriptor(i),
            attribute_it,
            cccd_created
        );
        if (err) {
            return err;
        }
    }

    // insert implicit CCCD
    if ((properties & UPDATE_PROPERTIES) && (cccd_created == false)) {
        err = insert_cccd(characteristic, attribute_it);
        if (err) {
            return err;
        }
    }

    return BLE_ERROR_NONE;
}

bool GattServer::is_characteristic_valid(GattCharacteristic *characteristic) {
    uint8_t properties = characteristic->getProperties();

    // nothing to read while the characteristic is flagged as readable
    if ((characteristic->getValueAttribute().getValuePtr() == NULL) &&
        (characteristic->getValueAttribute().getMaxLength() == 0) &&
        (properties == READ_PROPERTY) &&
        (characteristic->isReadAuthorizationEnabled() == false)
    ) {
        return false;
    }

    // nothing to write while the characteristic is flagged as writable
    if ((characteristic->getValueAttribute().getValuePtr() == NULL) &&
        (characteristic->getValueAttribute().getMaxLength() == 0) &&
        (properties & WRITABLE_PROPERTIES) &&
        (characteristic->isWriteAuthorizationEnabled() == false)
    ) {
        return false;
    }

#if BLE_FEATURE_SIGNING
    // check for invalid permissions
    if ((properties == SIGNED_WRITE_PROPERTY) &&
        (characteristic->getWriteSecurityRequirement() == att_security_requirement_t::NONE
#if BLE_FEATURE_SECURE_CONNECTIONS
         || characteristic->getWriteSecurityRequirement() == att_security_requirement_t::SC_AUTHENTICATED

#endif // BLE_FEATURE_SECURE_CONNECTIONS
        )
    ) {
        return false;
    }
#endif // BLE_FEATURE_SIGNING

    return true;
}

void GattServer::insert_characteristic_declaration_attribute(
    GattCharacteristic *characteristic,
    attsAttr_t *&attribute_it
) {
    const UUID& value_uuid = characteristic->getValueAttribute().getUUID();

    // move the current handle to point to the value handle
    currentHandle += 2;
    characteristic->getValueAttribute().setHandle(currentHandle);

    // fill the cordio attribute
    attribute_it->pUuid = attChUuid;
    attribute_it->maxLen = 1 + sizeof(currentHandle) + value_uuid.getLen();
    attribute_it->pLen = &attribute_it->maxLen;
    attribute_it->pValue = (uint8_t*) alloc_block(attribute_it->maxLen);
    attribute_it->settings = 0;
    attribute_it->permissions = ATTS_PERMIT_READ;

    // set the attribute value
    uint8_t *value_it = attribute_it->pValue;
    *value_it++ = characteristic->getProperties();
    memcpy(value_it, &currentHandle, sizeof(currentHandle));
    value_it += sizeof(currentHandle);
    memcpy(value_it, value_uuid.getBaseUUID(), value_uuid.getLen());

    ++attribute_it;
}

ble_error_t GattServer::insert_characteristic_value_attribute(
    GattCharacteristic *characteristic,
    attsAttr_t *&attribute_it
) {
    GattAttribute &value_attribute = characteristic->getValueAttribute();
    uint8_t properties = characteristic->getProperties();

    // note: currentHandle has been already moved to the correct value

    // Create Value Attribute
    attribute_it->pUuid = value_attribute.getUUID().getBaseUUID();
    attribute_it->maxLen = characteristic->getValueAttribute().getMaxLength();
    attribute_it->pLen = (uint16_t*) alloc_block(attribute_it->maxLen + sizeof(uint16_t));
    *attribute_it->pLen = value_attribute.getLength();
    attribute_it->pValue = (uint8_t*) ((uint16_t*)attribute_it->pLen + 1);
    memcpy(attribute_it->pValue, value_attribute.getValuePtr(), *attribute_it->pLen);
    memset(attribute_it->pValue + *attribute_it->pLen, 0, attribute_it->maxLen - *attribute_it->pLen);

    // Set value attribute settings
    attribute_it->settings = 0;

    if (properties & READ_PROPERTY) {
        attribute_it->settings |= ATTS_SET_READ_CBACK;
    }
    if (properties & WRITABLE_PROPERTIES) {
        attribute_it->settings |= ATTS_SET_WRITE_CBACK;
    }
    if (value_attribute.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) {
        attribute_it->settings |= ATTS_SET_UUID_128;
    }
    if (value_attribute.hasVariableLength()) {
        attribute_it->settings |= ATTS_SET_VARIABLE_LEN;
    }
    if (properties & SIGNED_WRITE_PROPERTY) {
        attribute_it->settings |= ATTS_SET_ALLOW_SIGNED;
    }

    // setup permissions
    attribute_it->permissions = 0;

    // configure read permission
    if (properties & READ_PROPERTY) {
        attribute_it->permissions |= ATTS_PERMIT_READ;
        switch (characteristic->getReadSecurityRequirement().value()) {
            case att_security_requirement_t::NONE:
                break;
#if BLE_FEATURE_SECURITY
            case att_security_requirement_t::UNAUTHENTICATED:
                attribute_it->permissions |= ATTS_PERMIT_READ_ENC;
                break;
            case att_security_requirement_t::AUTHENTICATED:
                attribute_it->permissions |=
                    ATTS_PERMIT_READ_ENC |
                    ATTS_PERMIT_READ_AUTH;
                break;
#if BLE_FEATURE_SECURE_CONNECTIONS
            case att_security_requirement_t::SC_AUTHENTICATED:
                // Note: check done in the cordio stack doesn't cover LESC
                // so this one is done in attsAuthorCback
                attribute_it->permissions |=
                    ATTS_PERMIT_READ_ENC |
                    ATTS_PERMIT_READ_AUTH |
                    ATTS_PERMIT_READ_AUTHORIZ;
                break;
#endif // BLE_FEATURE_SECURE_CONNECTIONS
#endif // BLE_FEATURE_SECURITY
        }
    }

    // configure write permission
    if (properties & WRITABLE_PROPERTIES) {
        attribute_it->permissions |= ATTS_PERMIT_WRITE;
        switch (characteristic->getWriteSecurityRequirement().value()) {
            case att_security_requirement_t::NONE:
                break;
#if BLE_FEATURE_SECURITY
            case att_security_requirement_t::UNAUTHENTICATED:
                attribute_it->permissions |= ATTS_PERMIT_WRITE_ENC;
                break;
            case att_security_requirement_t::AUTHENTICATED:
                attribute_it->permissions |=
                    ATTS_PERMIT_WRITE_ENC |
                    ATTS_PERMIT_WRITE_AUTH;
                break;
#if BLE_FEATURE_SECURE_CONNECTIONS
            case att_security_requirement_t::SC_AUTHENTICATED:
                // Note: check done in the cordio stack doesn't cover LESC
                // so this one is done in attsAuthorCback
                attribute_it->permissions |=
                    ATTS_PERMIT_WRITE_ENC |
                    ATTS_PERMIT_WRITE_AUTH |
                    ATTS_PERMIT_WRITE_AUTHORIZ;
                break;
#endif // BLE_FEATURE_SECURE_CONNECTIONS
#endif // BLE_FEATURE_SECURITY
        }
    }

    // Register characteristic in authorisation list
    // Note: ATTS_PERMIT_*_AUTHORIZ is uniquely used to check if security
    // requirements are met according to the security requirements set in the
    // characteristic.
    // User defined security authorisation does not impact this flag
    if ((attribute_it->permissions & (ATTS_PERMIT_READ_AUTHORIZ | ATTS_PERMIT_WRITE_AUTHORIZ)) ||
        (properties & UPDATE_PROPERTIES) ||
        characteristic->isReadAuthorizationEnabled() ||
        characteristic->isWriteAuthorizationEnabled()
    ) {
        if ( _auth_char_count >= MAX_CHARACTERISTIC_AUTHORIZATION_CNT) {
            return BLE_ERROR_NO_MEM;
        }
        _auth_char[_auth_char_count] = characteristic;
        ++_auth_char_count;
    }

    ++attribute_it;

    return BLE_ERROR_NONE;
}

ble_error_t GattServer::insert_descriptor(
    GattCharacteristic *characteristic,
    GattAttribute* descriptor,
    attsAttr_t *&attribute_it,
    bool& cccd_created
) {
    uint8_t properties = characteristic->getProperties();

    currentHandle++;

    descriptor->setHandle(currentHandle);

    attribute_it->pUuid = descriptor->getUUID().getBaseUUID();
    attribute_it->maxLen = descriptor->getMaxLength();
    attribute_it->pLen = (uint16_t*) alloc_block(attribute_it->maxLen + sizeof(uint16_t));
    *attribute_it->pLen = descriptor->getLength();
    attribute_it->pValue = (uint8_t*) ((uint16_t*)attribute_it->pLen + 1);
    memcpy(attribute_it->pValue, descriptor->getValuePtr(), *attribute_it->pLen);
    memset(attribute_it->pValue + *attribute_it->pLen, 0, attribute_it->maxLen - *attribute_it->pLen);

    attribute_it->settings = 0;

    if (descriptor->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) {
        attribute_it->settings |= ATTS_SET_UUID_128;
    }

    // handle the special case of a CCCD
    if (descriptor->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) {
        if (cccd_cnt >= MAX_CCCD_CNT) {
            return BLE_ERROR_NO_MEM;
        }

        if (descriptor->isReadAllowed() == false ||
            descriptor->getReadSecurityRequirement() != att_security_requirement_t::NONE
        ) {
            return BLE_ERROR_INVALID_PARAM;
        }

        cccd_created = true;
        attribute_it->settings |= ATTS_SET_CCC;

        cccds[cccd_cnt].handle = currentHandle;
        cccds[cccd_cnt].valueRange = 0;
        if (properties & NOTIFY_PROPERTY) {
            cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_NOTIFY;
        }
        if (properties & INDICATE_PROPERTY) {
            cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_INDICATE;
        }
        cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle();
        cccd_cnt++;
    }

    if (descriptor->hasVariableLength()) {
        attribute_it->settings |= ATTS_SET_VARIABLE_LEN;
    }

    // setup permissions
    attribute_it->permissions = 0;

    // configure read permission
    if (descriptor->isReadAllowed()) {
        attribute_it->permissions |= ATTS_PERMIT_READ;
        switch (descriptor->getReadSecurityRequirement().value()) {
            case att_security_requirement_t::NONE:
                break;
#if BLE_FEATURE_SECURITY
            case att_security_requirement_t::UNAUTHENTICATED:
                attribute_it->permissions |= ATTS_PERMIT_READ_ENC;
                break;
            case att_security_requirement_t::AUTHENTICATED:
                attribute_it->permissions |=
                    ATTS_PERMIT_READ_ENC |
                    ATTS_PERMIT_READ_AUTH;
                break;
#if BLE_FEATURE_SECURE_CONNECTIONS
            case att_security_requirement_t::SC_AUTHENTICATED:
                // Note: check done in the cordio stack doesn't cover LESC
                // so this one is done in attsAuthorCback
                attribute_it->permissions |=
                    ATTS_PERMIT_READ_ENC |
                    ATTS_PERMIT_READ_AUTH |
                    ATTS_PERMIT_READ_AUTHORIZ;
                break;
#endif // BLE_FEATURE_SECURE_CONNECTIONS
#endif // BLE_FEATURE_SECURITY
        }

        if (properties & READ_PROPERTY && !(attribute_it->settings & ATTS_SET_CCC)) {
            attribute_it->settings |= ATTS_SET_READ_CBACK;
        }
    }

    // configure write permission
    if (descriptor->isWriteAllowed()) {
        attribute_it->permissions |= ATTS_PERMIT_WRITE;
        switch (descriptor->getWriteSecurityRequirement().value()) {
            case att_security_requirement_t::NONE:
                break;
#if BLE_FEATURE_SECURITY
            case att_security_requirement_t::UNAUTHENTICATED:
                attribute_it->permissions |= ATTS_PERMIT_WRITE_ENC;
                break;
            case att_security_requirement_t::AUTHENTICATED:
                attribute_it->permissions |=
                    ATTS_PERMIT_WRITE_ENC |
                    ATTS_PERMIT_WRITE_AUTH;
                break;
#if BLE_FEATURE_SECURE_CONNECTIONS
            case att_security_requirement_t::SC_AUTHENTICATED:
                // Note: check done in the cordio stack doesn't cover LESC
                // so this one is done in attsAuthorCback
                attribute_it->permissions |=
                    ATTS_PERMIT_WRITE_ENC |
                    ATTS_PERMIT_WRITE_AUTH |
                    ATTS_PERMIT_WRITE_AUTHORIZ;
                break;
#endif // BLE_FEATURE_SECURE_CONNECTIONS
#endif // BLE_FEATURE_SECURITY
        }

        if (properties & WRITABLE_PROPERTIES && !(attribute_it->settings & ATTS_SET_CCC)) {
            attribute_it->settings |= ATTS_SET_WRITE_CBACK;
        }
    }

    attribute_it++;
    return BLE_ERROR_NONE;
}

ble_error_t GattServer::insert_cccd(
    GattCharacteristic *characteristic,
    attsAttr_t *&attribute_it
) {
    if (cccd_cnt >= MAX_CCCD_CNT) {
        return BLE_ERROR_NO_MEM;
    }

    uint8_t properties = characteristic->getProperties();

    currentHandle++;

    attribute_it->pUuid = CCCD_UUID.getBaseUUID();
    attribute_it->pValue = (uint8_t*) &cccd_values[cccd_cnt];
    attribute_it->maxLen = CCCD_SIZE;
    attribute_it->pLen = &attribute_it->maxLen;
    attribute_it->settings = ATTS_SET_CCC;
    attribute_it->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE);

    cccds[cccd_cnt].handle = currentHandle;
    cccds[cccd_cnt].valueRange = 0;
    if (properties & NOTIFY_PROPERTY) {
        cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_NOTIFY;
    }
    if (properties & INDICATE_PROPERTY) {
        cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_INDICATE;
    }
    cccds[cccd_cnt].secLevel = characteristic->getUpdateSecurityRequirement().value();
    cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle();

    cccd_cnt++;
    attribute_it++;

    return BLE_ERROR_NONE;
}

ble_error_t GattServer::read_(
    GattAttribute::Handle_t att_handle,
    uint8_t buffer[],
    uint16_t * buffer_length
) {
    uint16_t att_length = 0;
    uint8_t* att_value = NULL;

    if (AttsGetAttr(att_handle, &att_length, &att_value) != ATT_SUCCESS) {
        return BLE_ERROR_PARAM_OUT_OF_RANGE;
    }

    if (buffer) {
        memcpy(buffer, att_value, std::min(*buffer_length, att_length));
    }

    *buffer_length = att_length;

    return BLE_ERROR_NONE;
}

ble_error_t GattServer::read_(
    connection_handle_t connection,
    GattAttribute::Handle_t att_handle,
    uint8_t buffer[],
    uint16_t *buffer_length
) {
    // Check to see if this is a CCCD
    uint8_t cccd_index;
    if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) {
        if (connection == DM_CONN_ID_NONE) {
            return BLE_ERROR_PARAM_OUT_OF_RANGE;
        }
        uint16_t cccd_value = AttsCccGet(connection, cccd_index);
        uint16_t cccd_length = sizeof(cccd_value);

        if (buffer) {
            memcpy(buffer, &cccd_value, std::min(*buffer_length, cccd_length));
        }

        *buffer_length = cccd_length;
        return BLE_ERROR_NONE;
    }

    // This is not a CCCD. Use the non-connection specific update method.
    return read(att_handle, buffer, buffer_length);
}

ble_error_t GattServer::write_(
    GattAttribute::Handle_t att_handle,
    const uint8_t buffer[],
    uint16_t len,
    bool local_only
) {
    // Check to see if this is a CCCD, if it is the case update the value for all
    // connections
    uint8_t cccd_index;
    if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) {
        if (len != sizeof(uint16_t)) {
            return BLE_ERROR_INVALID_PARAM;
        }

        uint16_t cccd_value;
        memcpy(&cccd_value, buffer, sizeof(cccd_value));

        for (dmConnId_t conn_id = DM_CONN_MAX; conn_id > DM_CONN_ID_NONE; --conn_id) {
            if (DmConnInUse(conn_id) == true) {
                AttsCccSet(conn_id, cccd_index, cccd_value);
            }
        }

        return BLE_ERROR_NONE;
    }

    // write the value to the attribute handle
    if (AttsSetAttr(att_handle, len, (uint8_t*)buffer) != ATT_SUCCESS) {
        return BLE_ERROR_PARAM_OUT_OF_RANGE;
    }

    // return if the update does not have to be propagated to peers
    if (local_only || !get_cccd_index_by_value_handle(att_handle, cccd_index)) {
        return BLE_ERROR_NONE;
    }

    // This characteristic has a CCCD attribute. Handle notifications and
    // indications for all active connections if the authentication is
    // successful
    size_t updates_sent = 0;

#if BLE_FEATURE_SECURITY
    for (dmConnId_t conn_id = DM_CONN_MAX; conn_id > DM_CONN_ID_NONE; --conn_id) {
        if (DmConnInUse(conn_id) == true) {
            if (is_update_authorized(conn_id, att_handle)) {
                uint16_t cccd_config = AttsCccEnabled(conn_id, cccd_index);
                if (cccd_config & ATT_CLIENT_CFG_NOTIFY) {
                    AttsHandleValueNtf(conn_id, att_handle, len, (uint8_t*)buffer);
                    updates_sent++;
                }
                if (cccd_config & ATT_CLIENT_CFG_INDICATE) {
                    AttsHandleValueInd(conn_id, att_handle, len, (uint8_t*)buffer);
                    updates_sent++;
                }
            }
        }
    }
#endif // BLE_FEATURE_SECURITY

    return BLE_ERROR_NONE;
}

ble_error_t GattServer::write_(
    connection_handle_t connection,
    GattAttribute::Handle_t att_handle,
    const uint8_t buffer[],
    uint16_t len,
    bool local_only
) {
    // Check to see if this is a CCCD
    uint8_t cccd_index;
    if (get_cccd_index_by_cccd_handle(att_handle, cccd_index)) {
        if ((connection == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits
            return BLE_ERROR_PARAM_OUT_OF_RANGE;
        }

        uint16_t cccd_value;
        memcpy(&cccd_value, buffer, sizeof(cccd_value));
        AttsCccSet(connection, cccd_index, cccd_value);
        return BLE_ERROR_NONE;
    }

    // write the value to the attribute handle
    if (AttsSetAttr(att_handle, len, (uint8_t*)buffer) != ATT_SUCCESS) {
        return BLE_ERROR_PARAM_OUT_OF_RANGE;
    }

    // return if the update does not have to be propagated to peers
    if (local_only || !get_cccd_index_by_value_handle(att_handle, cccd_index)) {
        return BLE_ERROR_NONE;
    }

    // This characteristic has a CCCD attribute. Handle notifications and indications.
    size_t updates_sent = 0;

#if BLE_FEATURE_SECURITY
    if (is_update_authorized(connection, att_handle)) {
        uint16_t cccEnabled = AttsCccEnabled(connection, cccd_index);
        if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) {
            AttsHandleValueNtf(connection, att_handle, len, (uint8_t*)buffer);
            updates_sent++;
        }
        if (cccEnabled & ATT_CLIENT_CFG_INDICATE) {
            AttsHandleValueInd(connection, att_handle, len, (uint8_t*)buffer);
            updates_sent++;
        }
    }
#endif // BLE_FEATURE_SECURITY

    return BLE_ERROR_NONE;
}

ble_error_t GattServer::areUpdatesEnabled_(
    const GattCharacteristic &characteristic,
    bool *enabled
) {
    for (size_t idx = 0; idx < cccd_cnt; idx++) {
        if (characteristic.getValueHandle() == cccd_handles[idx]) {
            for (dmConnId_t conn_id = DM_CONN_MAX; conn_id > DM_CONN_ID_NONE; --conn_id) {
                if (DmConnInUse(conn_id) == true) {
                    uint16_t cccd_value = AttsCccGet(conn_id, idx);
                    if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) {
                        *enabled = true;
                        return BLE_ERROR_NONE;
                    }

                }
            }
            *enabled = false;
            return BLE_ERROR_NONE;
        }
    }

    return BLE_ERROR_PARAM_OUT_OF_RANGE;
}

ble_error_t GattServer::areUpdatesEnabled_(
    connection_handle_t connectionHandle,
    const GattCharacteristic &characteristic,
    bool *enabled
) {
    if (connectionHandle == DM_CONN_ID_NONE) {
        return BLE_ERROR_INVALID_PARAM;
    }

    for (uint8_t idx = 0; idx < cccd_cnt; idx++) {
        if (characteristic.getValueHandle() == cccd_handles[idx]) {
            uint16_t cccd_value = AttsCccGet(connectionHandle, idx);
            if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) {
                *enabled = true;
            } else {
                *enabled = false;
            }
            return BLE_ERROR_NONE;
        }
    }
    return BLE_ERROR_PARAM_OUT_OF_RANGE;
}

bool GattServer::isOnDataReadAvailable_() const
{
    return true;
}

::Gap::ConnectionParams_t GattServer::getPreferredConnectionParams()
{
    ::Gap::ConnectionParams_t params = { 0 };
    memcpy(&params.minConnectionInterval, generic_access_service.ppcp, 2);
    memcpy(&params.maxConnectionInterval, generic_access_service.ppcp + 2, 2);
    memcpy(&params.slaveLatency, generic_access_service.ppcp + 4, 2);
    memcpy(&params.connectionSupervisionTimeout, generic_access_service.ppcp + 6, 2);
    return params;
}

void GattServer::setPreferredConnectionParams(const ::Gap::ConnectionParams_t& params)
{
    memcpy(generic_access_service.ppcp, &params.minConnectionInterval, 2);
    memcpy(generic_access_service.ppcp + 2, &params.maxConnectionInterval, 2);
    memcpy(generic_access_service.ppcp + 4, &params.slaveLatency, 2);
    memcpy(generic_access_service.ppcp + 6, &params.connectionSupervisionTimeout, 2);
}

ble_error_t GattServer::setDeviceName(const uint8_t *deviceName)
{
    size_t length = 0;

    if (deviceName != NULL) {
        length = strlen((const char*)deviceName);
    }

    if (length == 0) {
        free(generic_access_service.device_name_value());
    } else {
        uint8_t* res = (uint8_t*) realloc(generic_access_service.device_name_value(), length);
        if (res == NULL) {
            return BLE_ERROR_NO_MEM;
        }

        generic_access_service.device_name_value() = res;
        memcpy(res, deviceName, length);
    }

    generic_access_service.device_name_length = length;

    return BLE_ERROR_NONE;
}

void GattServer::getDeviceName(const uint8_t*& name, uint16_t& length)
{
    length = generic_access_service.device_name_length;
    name = generic_access_service.device_name_value();
}

void GattServer::setAppearance(GapAdvertisingData::Appearance appearance)
{
    generic_access_service.appearance = appearance;
}

GapAdvertisingData::Appearance GattServer::getAppearance()
{
    return (GapAdvertisingData::Appearance) generic_access_service.appearance;
}

ble_error_t GattServer::reset_(void)
{
    Base::reset_();

    while (registered_service) {
        internal_service_t* s = registered_service;
        registered_service = s->next;
        AttsRemoveGroup(s->attGroup.startHandle);
        delete s;
    }

    while (allocated_blocks) {
        alloc_block_t* b = allocated_blocks;
        allocated_blocks = b->next;
        free(b);
    }

    AttsRemoveGroup(generic_access_service.service.startHandle);
    AttsRemoveGroup(generic_attribute_service.service.startHandle);
    free(generic_access_service.device_name_value());

    currentHandle = 0;
    cccd_cnt = 0;

    _auth_char_count = 0;

    AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb);

    return BLE_ERROR_NONE;
}

void GattServer::cccd_cb(attsCccEvt_t *evt)
{
    GattServerEvents::gattEvent_t evt_type =
        evt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE) ?
            GattServerEvents::GATT_EVENT_UPDATES_ENABLED :
            GattServerEvents::GATT_EVENT_UPDATES_DISABLED;

    getInstance().handleEvent(evt_type, evt->handle);
}

void GattServer::att_cb(const attEvt_t *evt)
{
    if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATT_MTU_UPDATE_IND) {
        ::GattServer::EventHandler *handler = getInstance().getEventHandler();
        if (handler) {
            handler->onAttMtuChange(evt->hdr.param, evt->mtu);
        }
    } else if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATTS_HANDLE_VALUE_CNF) {
        getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, evt->handle);
    }
}

uint8_t GattServer::atts_read_cb(
    dmConnId_t connId,
    uint16_t handle,
    uint8_t operation,
    uint16_t offset,
    attsAttr_t *pAttr
) {
    GattCharacteristic* auth_char = getInstance().get_auth_char(handle);
    if (auth_char && auth_char->isReadAuthorizationEnabled()) {
        GattReadAuthCallbackParams read_auth_params = {
            connId,
            handle,
            offset,
            /* len */ 0,
            /* data */ NULL,
            AUTH_CALLBACK_REPLY_SUCCESS
        };

        GattAuthCallbackReply_t ret = auth_char->authorizeRead(&read_auth_params);
        if (ret != AUTH_CALLBACK_REPLY_SUCCESS) {
            return ret & 0xFF;
        }

        pAttr->pValue = read_auth_params.data;
        *pAttr->pLen = read_auth_params.len;
    }

    GattReadCallbackParams read_params = {
        connId,
        handle,
        offset,
        *pAttr->pLen,
        pAttr->pValue,
        /* status */ BLE_ERROR_NONE,
    };
    getInstance().handleDataReadEvent(&read_params);

    return ATT_SUCCESS;
}

uint8_t GattServer::atts_write_cb(
    dmConnId_t connId,
    uint16_t handle,
    uint8_t operation,
    uint16_t offset,
    uint16_t len,
    uint8_t *pValue,
    attsAttr_t *pAttr
) {
    uint8_t err;

    /* TODO: offset is not handled properly */
    if ((err = AttsSetAttr(handle, len, pValue)) != ATT_SUCCESS) {
        return err;
    }

    GattWriteCallbackParams::WriteOp_t writeOp;
    switch (operation) {
        case ATT_PDU_WRITE_REQ:
            writeOp = GattWriteCallbackParams::OP_WRITE_REQ;
            break;
        case ATT_PDU_WRITE_CMD:
            writeOp = GattWriteCallbackParams::OP_WRITE_CMD;
            break;
#if BLE_FEATURE_SIGNING
        case ATT_PDU_SIGNED_WRITE_CMD:
            if (getInstance()._signing_event_handler) {
                getInstance()._signing_event_handler->on_signed_write_received(
                    connId,
                    AttsGetSignCounter(connId)
                );
            }
            writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD;
            break;
#endif // BLE_FEATURE_SIGNING
        case ATT_PDU_PREP_WRITE_REQ:
            writeOp = GattWriteCallbackParams::OP_PREP_WRITE_REQ;
            break;
        case ATT_PDU_EXEC_WRITE_REQ:
            writeOp = GattWriteCallbackParams::OP_EXEC_WRITE_REQ_NOW;
            break;
        default:
            writeOp = GattWriteCallbackParams::OP_INVALID;
            break;
    }

    GattCharacteristic* auth_char = getInstance().get_auth_char(handle);
    if (auth_char && auth_char->isWriteAuthorizationEnabled()) {
        GattWriteAuthCallbackParams write_auth_params = {
            connId,
            handle,
            offset,
            len,
            pValue,
            AUTH_CALLBACK_REPLY_SUCCESS
        };

        GattAuthCallbackReply_t ret = auth_char->authorizeWrite(&write_auth_params);
        if (ret!= AUTH_CALLBACK_REPLY_SUCCESS) {
            return ret & 0xFF;
        }
    }

    GattWriteCallbackParams write_params = {
        connId,
        handle,
        writeOp,
        offset,
        len,
        pValue
    };
    getInstance().handleDataWrittenEvent(&write_params);

    return ATT_SUCCESS;
}

uint8_t GattServer::atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle)
{
#if BLE_FEATURE_SECURITY
    // this CB is triggered when read or write of an attribute (either a value
    // handle or a descriptor) requires secure connection security.
    SecurityManager& security_manager = BLE::deviceInstance().getSecurityManager();

    link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED);
    ble_error_t err = security_manager.getLinkEncryption(connId, &encryption);
    if (err) {
        return ATT_ERR_AUTH;
    }

    if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) {
        return ATT_ERR_AUTH;
    }

    return ATT_SUCCESS;
#else
    return ATT_ERR_AUTH;
#endif
}

void GattServer::add_generic_access_service()
{
    ++currentHandle;
    generic_access_service.service.pNext = NULL;
    generic_access_service.service.startHandle = currentHandle;
    generic_access_service.service.readCback = atts_read_cb;
    generic_access_service.service.writeCback = atts_write_cb;

    // bind attributes to the service
    generic_access_service.service.pAttr = generic_access_service.attributes;

    attsAttr_t* current_attribute = generic_access_service.attributes;

    // service attribute
    current_attribute->pUuid = attPrimSvcUuid;
    current_attribute->pValue = (uint8_t*) attGapSvcUuid;
    current_attribute->maxLen = sizeof(attGapSvcUuid);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // device name declaration
    currentHandle += 2; // note: incremented by two to get a pointer to the value handle
    ++current_attribute;

    // set properties
    generic_access_service.device_name_declaration_value[0] = ATT_PROP_READ;
    // set value handle
    memcpy(generic_access_service.device_name_declaration_value + 1, &currentHandle, sizeof(currentHandle));
    // set the characteristic UUID
    memcpy(generic_access_service.device_name_declaration_value + 3, attDnChUuid, sizeof(attDnChUuid));

    current_attribute->pUuid = attChUuid;
    current_attribute->pValue = generic_access_service.device_name_declaration_value;
    current_attribute->maxLen = sizeof(generic_access_service.device_name_declaration_value);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // device name value
    ++current_attribute;
    generic_access_service.device_name_length = 0;
    current_attribute->pUuid = attDnChUuid;
    current_attribute->maxLen = 248;
    current_attribute->pLen = &generic_access_service.device_name_length;
    current_attribute->pValue = NULL;
    current_attribute->settings = ATTS_SET_VARIABLE_LEN;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // appearance declaration
    currentHandle += 2; // note: incremented by two to get a pointer to the value handle
    ++current_attribute;

    // set properties
    generic_access_service.appearance_declaration_value[0] = ATT_PROP_READ;
    // set value handle
    memcpy(generic_access_service.appearance_declaration_value + 1, &currentHandle, sizeof(currentHandle));
    // set the characteristic UUID
    memcpy(generic_access_service.appearance_declaration_value + 3, attApChUuid, sizeof(attApChUuid));

    current_attribute->pUuid = attChUuid;
    current_attribute->pValue = generic_access_service.appearance_declaration_value;
    current_attribute->maxLen = sizeof(generic_access_service.appearance_declaration_value);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // appearance value
    ++current_attribute;
    generic_access_service.appearance = 0; // unknown appearance
    current_attribute->pUuid = attApChUuid;
    current_attribute->maxLen = sizeof(generic_access_service.appearance);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->pValue = (uint8_t*) &generic_access_service.appearance;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // peripheral prefered connection parameters declaration
    currentHandle += 2; // note: incremented by two to get a pointer to the value handle
    ++current_attribute;

    // set properties
    generic_access_service.ppcp_declaration_value[0] = ATT_PROP_READ;
    // set value handle
    memcpy(generic_access_service.ppcp_declaration_value + 1, &currentHandle, sizeof(currentHandle));
    // set the characteristic UUID
    memcpy(generic_access_service.ppcp_declaration_value + 3, attPpcpChUuid, sizeof(attPpcpChUuid));

    current_attribute->pUuid = attChUuid;
    current_attribute->pValue = generic_access_service.ppcp_declaration_value;
    current_attribute->maxLen = sizeof(generic_access_service.ppcp_declaration_value);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // peripheral prefered connection parameters value
    ++current_attribute;
    const uint8_t default_ppcp_value[] = {
        0xFF, 0xFF, // no specific min connection interval
        0xFF, 0xFF, // no specific max connection interval
        0x00, 0x00, // no slave latency
        0xFF, 0xFF // no specific connection supervision timeout
    };
    memcpy(&generic_access_service.ppcp, default_ppcp_value, sizeof(default_ppcp_value));
    current_attribute->pUuid = attPpcpChUuid;
    current_attribute->maxLen = sizeof(generic_access_service.ppcp);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->pValue = generic_access_service.ppcp;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    generic_access_service.service.endHandle = currentHandle;
    AttsAddGroup(&generic_access_service.service);
}

void GattServer::add_generic_attribute_service()
{
    ++currentHandle;
    generic_attribute_service.service.pNext = NULL;
    generic_attribute_service.service.startHandle = currentHandle;
    generic_attribute_service.service.readCback = atts_read_cb;
    generic_attribute_service.service.writeCback = atts_write_cb;

    // bind attributes to the service
    generic_attribute_service.service.pAttr = generic_attribute_service.attributes;

    attsAttr_t* current_attribute = generic_attribute_service.attributes;

    // service attribute
    current_attribute->pUuid = attPrimSvcUuid;
    current_attribute->pValue = (uint8_t*) attGattSvcUuid;
    current_attribute->maxLen = sizeof(attGattSvcUuid);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // service changed declaration
    currentHandle += 2; // note: incremented by two to get a pointer to the value handle
    ++current_attribute;

    // set properties
    generic_attribute_service.service_changed_declaration[0] = ATT_PROP_INDICATE;
    // set value handle
    memcpy(generic_attribute_service.service_changed_declaration + 1, &currentHandle, sizeof(currentHandle));
    // set the characteristic UUID
    memcpy(generic_attribute_service.service_changed_declaration + 3, attScChUuid, sizeof(attScChUuid));

    current_attribute->pUuid = attChUuid;
    current_attribute->pValue = generic_attribute_service.service_changed_declaration;
    current_attribute->maxLen = sizeof(generic_attribute_service.service_changed_declaration);
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = 0;
    current_attribute->permissions = ATTS_PERMIT_READ;

    // service changed value
    ++current_attribute;
    current_attribute->pUuid = attScChUuid;
    current_attribute->maxLen = 0;
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->pValue = NULL;
    current_attribute->settings = 0;
    current_attribute->permissions = 0;

    // CCCD
    ++current_attribute;
    current_attribute->pUuid = attCliChCfgUuid;
    current_attribute->pValue = (uint8_t*)&cccd_values[cccd_cnt];
    current_attribute->maxLen = 2;
    current_attribute->pLen = &current_attribute->maxLen;
    current_attribute->settings = ATTS_SET_CCC;
    current_attribute->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE);

    cccds[cccd_cnt].handle = currentHandle;
    cccds[cccd_cnt].valueRange = ATT_CLIENT_CFG_INDICATE;
    cccds[cccd_cnt].secLevel = DM_SEC_LEVEL_NONE;
    cccd_handles[cccd_cnt] = currentHandle - 1;
    cccd_cnt++;

    generic_attribute_service.service.endHandle = currentHandle;
    AttsAddGroup(&generic_attribute_service.service);
    AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb);
}

void* GattServer::alloc_block(size_t block_size) {
    alloc_block_t* block = (alloc_block_t*) malloc(sizeof(alloc_block_t) + block_size);
    if (block == NULL) {
        return NULL;
    }

    if (allocated_blocks) {
        block->next = allocated_blocks;
    } else {
        block->next = NULL;
    }

    allocated_blocks = block;

    return block->data;
}

GattCharacteristic* GattServer::get_auth_char(uint16_t value_handle)
{
    for (size_t i = 0; i < _auth_char_count; ++i) {
        if (_auth_char[i]->getValueHandle() == value_handle) {
            return _auth_char[i];
        }
    }
    return NULL;
}

bool GattServer::get_cccd_index_by_cccd_handle(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const
{
    for (idx = 0; idx < cccd_cnt; idx++) {
        if (cccd_handle == cccds[idx].handle) {
            return true;
        }
    }
    return false;
}

bool GattServer::get_cccd_index_by_value_handle(GattAttribute::Handle_t char_handle, uint8_t& idx) const
{
    for (idx = 0; idx < cccd_cnt; ++idx) {
        if (char_handle == cccd_handles[idx]) {
            return true;
        }
    }
    return false;
}

bool GattServer::is_update_authorized(
    connection_handle_t connection,
    GattAttribute::Handle_t value_handle
) {
    GattCharacteristic* auth_char = get_auth_char(value_handle);
    if (!auth_char) {
        return true;
    }

    att_security_requirement_t sec_req =
        auth_char->getUpdateSecurityRequirement();

    if (sec_req == att_security_requirement_t::NONE) {
        return true;
    }

#if BLE_FEATURE_SECURITY
    SecurityManager& security_manager = BLE::deviceInstance().getSecurityManager();
    link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED);
    ble_error_t err = security_manager.getLinkEncryption(connection, &encryption);
    if (err) {
        return false;
    }
#endif // BLE_FEATURE_SECURITY

    switch (sec_req.value()) {
#if BLE_FEATURE_SECURITY
        case att_security_requirement_t::UNAUTHENTICATED:
            if (encryption < link_encryption_t::ENCRYPTED) {
                return false;
            }
            return true;

        case att_security_requirement_t::AUTHENTICATED:
            if (encryption < link_encryption_t::ENCRYPTED_WITH_MITM) {
                return false;
            }
            return true;
#if BLE_FEATURE_SECURE_CONNECTIONS
        case att_security_requirement_t::SC_AUTHENTICATED:
            if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) {
                return false;
            }
            return true;
#endif // BLE_FEATURE_SECURE_CONNECTIONS
#endif // BLE_FEATURE_SECURITY
        default:
            return false;
    }
}

GattServer::GattServer() :
    _signing_event_handler(NULL),
    cccds(),
    cccd_values(),
    cccd_handles(),
    cccd_cnt(0),
    _auth_char(),
    _auth_char_count(0),
    generic_access_service(),
    generic_attribute_service(),
    registered_service(NULL),
    allocated_blocks(NULL),
    currentHandle(0),
    default_services_added(false)
{
}

} // namespace cordio
} // namespace vendor
} // namespace ble

redpajama_set_name: RedPajamaGithub


The Eastern region artists are accusing the Eastern region Radio and Tv presenters of not helping them in Creative Arts industry.
Speaking to some of the artists in Koforidua, nkawkaw, Akim Oda, Suhum and Somanya, they said the presenters are not helping them promote their songs.
One big artist name withheld in a conversation with a secret investigator said, there are some biggest artists in the region who need just a little push from the presenters to excel to the whole country and the world at large.
He made emphasis to how other region artists are excelling faster than them just because, their presenters are helpful and think of them in the industry.
"I don't see any help Eastern presenters are giving us. They always accuse us of producing bad songs but what is the difference between our songs and songs produced from other regions?. Some of our lyrics are even better than them. The Eastern presenters are not just helping us" he said with emotion.
They are therefore appealing to the Presenters Association in the Eastern Region to put measures in place to help promote them massively.
Finally, they promised not to forget them when they succeed in the industry.


The fund raiser is to support Peace programs both domestically and internationally to support campers as they transition back into there communities after camp. It allows them opportunities for leadership and self growth as they are dealing with the conflicts that live in including the Middle East and South Asian conflicts.
Be the first to Donate to Eugene and SeedsOfPeaceSU.


Rodriguez, a one-time gang member and now acclaimed author, poet and activist, worked with gang-involved and non-gang youth in Chicago from 1985 to 2000, founding the organization Youth Struggling for Survival. He's now based in Los Angeles and travels widely, speaking in jails, prisons, and juvenile facilities, among other locations. He was the vice-presidential candidate of the Justice Party in 2012 and is now running for the Green Party nomination for governor of California.
His program is to turn young people on to creative expression and to healing through native spiritual traditions.
"What are the alternatives? That's where people have got to think about imagination, cultural spaces in every neighborhood for expression, healing — if it's educational, if it's spiritual, if all the churches would open up, if all the schools would open up, you would stop a lot of this violence. And it doesn't cost anywhere near as much as it's costing us to put people away….
I asked Carrizales what he thought the city should be doing.
"What the city really needs to do is invest in the neighborhoods and build them up," he said.


text:
Tag Archives: UKIP
Vote UKIP
May 6, 2015 UncategorizedBritain, politics, UKIPChris
There's an election on. The procession of dickheads we usually see on the news grimly telling us the country's only hope is to lube up and take it are instead grinning and making promises akin to the young girlfriend assuring her man she'll wait for him as he's dragged off to the trenches, while eyeing up the bank clerk with flat feet. Policies that will never happen are being 'red lined' and 'set in stone' in a bid to make us all turn up to put a little pencil mark on a piece of paper some time on a Thursday. Life is absurd.
An election forces politicians out from behind their Civil Service forcefield and into our faces. This is when we get to find out if the latest batch should be applauded or ignored. In almost every case, the 2015 election has shown us that all they're interested in is telling us as little detail as possible about what they truly believe, while spreading fear of the other lot. Every Party Political Broadcast involves multiple mentions of how if you vote for anyone but 'us' you will be directly responsible for the maiming and murder of countless citizens by a coalition of cunts. It has been by far the most obfuscated and negative campaign of my adult life and if I could vote for Guy Fawkes I would.
But there is a glimmer of hope, suggesting that 2020 may not be as calamitous for democracy as this latest round of shit-shovelling. A new group has emerged as a powerful, proud force in politics, with policies we can believe in and people who are just like us. That group is UKIP, and a vote for UKIP is a vote for our future.
Now, anyone with a passing interest in anything I've ever said or done may be surprised at this apparent change of tack. But Russell Brand's example of comedic U-turning has given me courage to admit my real truth, I now realise. So, why UKIP?
Last night helped. A candidate for the party in Hampshire was suspended after being secretly filmed saying if his Conservative opponent of Sri Lankan heritage were ever to become Prime Minister he would 'personally put a bullet between his eyes'. The idea that a random Tory named Ranil Jayawardena could become only the second PM ever to be assassinated, and the remarkable train of events we'd need to witness to get to that point, sums up why I think we need UKIP.
Politics has become fucking boring, and UKIP make politics fun again.
Who doesn't hear 'UKIP' as the first word in a news report and experience a momentary exhilaration that the next two words might just be 'have suspended'? This is a party with a long track record of selecting candidates and councillors that epitomise what it means to be traditionally British – afraid of 'outsiders', furious at the notion anyone should get anything from 'the state' they don't deserve, jealous of other people's success and inexplicably fearful of the threat of random gay men to their anal virginity. Brown people are inherently terrifying. Change of any kind should be resisted at all costs. Feudalism can and will prevail.
And with that in mind UKIP's Dave Small was set loose on the internet last year with tweets about 'poofs and dykes', 'perverts' and 'Pakis'. Kerry Smith's choice phrases included 'disgusting poofters' and 'Chinky bird'. David Silvester called homosexuality a 'spiritual disease', which is the very worst kind of disease with the exception of arse cancer and hangovers.
Lynton Yates declared that anyone on benefits should be banned from driving because they 'really should catch the bus'. The famous Godfrey Bloom knows precisely where in the kitchen a woman's place is. Matthew Ellery was nicked for robbing his own dad's antiques shop. A whole raft of Kippers have been done for fiddling the books, while the best of all, Rozanne Duncan, declared unabashedly in a BBC TV programme that she had a problem with black people's faces and didn't really know why. She even had the style to admit she knew it was a slightly dubious viewpoint as she stood solidly by her lovely remarks.
Comedy even arises from the seemingly innocent. Roger Bird will forever be a hero of British politics for having stuck his cock in the wrong woman, who subsequently went public accusing him of all manner of misdemeanours. Interest was piqued as Roger, who looked 55 but turned out to be in his mid-30s, was enjoying fun times with a relatively attractive woman he would ordinarily have had little chance of penetrating. The upshot was he hadn't done much wrong, but how we laughed at this odd, balding, bespectacled little man.
It's because of each of these true Britons that I urge you to vote UKIP in the 2015 election. A UKIP majority government would be the most hilarious thing to have happpened in the politics of any country in humanity's colourful history. The mother of all democracies deserves to be the pace-setter in a new utopia of news reports that make us laugh, wince and scream with rage in equal measure. Politics can, and must, be a source of mirth in these tough times to be human.
Every other party any of us could vote for will take us on yet another ride on the staid, tiresome merry-go-round we've been throwing up on for 15 years or more. More cuts, more stories of hospitals having no money, more libraries shutting, more teachers quitting or going on strike, more families moved out of the areas they've lived in for generations to make way for expensive propertry developments, more pollution, more food banks, more of a gap between the rich and poor and, by far the worst of all, more pubs closing.
Can you see Nigel Farage ever letting a pub shut? All right, so it's a stretch to see that rubbery halfwit as Prime Minister for longer than about two and a half months before the people of Tottenham start burning down their own buildings again, someone declares Martial Law and we all get our first experience of the Home Office's shiny new water cannons. But what a time we'd have. Britain could be great again, recalling some of our wonderful country's finest moments, like the benevolent reign of Good King Richard III, the Charge of the Light Brigade, the Munich Agreement, Beagle 2, this summer's Ashes and that time the dear old Queen Mum got pissed on Beefeater and pissed on a Beefeater.
So, I urge every man, woman and eligible animal to vote UKIP. I'll vote Green to make sure it doesn't look like a fix – we're not Azerbaijan for Christ's sake. I'll take one for the team and try, somehow, to live with it. But if enough of you see purple as you enter the polling booth we could put this disgusting style of politics we've lapsed into to bed and finally return a bit of oomph to a country that's dying on its arse.
An aching legion of pine box evaders
October 10, 2014 Uncategorizedageing, civil rights, humanity, UKIPChris
Logan's Run, now there's a movie.
Based on the life expectancy figures that edge ever upwards year after year, most people eventually get old. Some don't; there will always be a child exploding in an electricity substation after reaching for his battered red Frisbee while the girl who made him go in there shouts "Jimmyyyyyyyyyyyyyyy!", and we call that 'Darwinism'.
If you don't know what that refers to, that means two things: one, you should probably put 'public information substation danger' into Youtube and watch how the government used to routinely shit us up over our fish fingers; and two, you're probably not old enough to need to care about getting old any time soon.
Good for you, because that might also mean you won't have to turn into a complete arsehole any time soon. Old people, almost universally, are scum, potentially deserving of the millions of volts poor Jimmy received, though in most old people that would probably have the same effect as Berocca does on the rest of us.
I have two examples from today alone. Firstly, obviously, an aching legion of pine box evaders in Clacton-on-Sea have voted in their greying thousands for UKIP to win their first MP. For weeks they have been on TV news moaning about anyone they've not known for decades as regular patrons of the local butcher. Foreigners eat dog and that's reason enough alone to vote UKIP, to protect JM Morley & Sons and ensure I get my pound of liver every fortnight without having to visit a supermarket filled with brown people. Old people eat liver by the way, another black mark.
The other example comes from Estonia where, in a rare good news story in the time of Ebola, ISIS and, well, UKIP, MPs have narrowly voted in favour of legalising gay marriage. The vote was 40 to 38 in favour and the massed ranks of decrepit Estonians were predictably furious at the result, having corralled their motorized pavement-clearing death machines into Talinn's main square to protest against this affront to decency. Honestly, my dear old ageing army of Estonia, I'd say you're overestimating your personal appeal if you think that law will affect you in any way.
Why do old people have to be so scared and angry about things the rest of see as basic human decency and equality? There's a natural tendency for old age to bring on a creeping move to the right wing of politics but, though it's generally accepted as fact, does anyone know why? They're getting nearer the grave, many of them believe in some form of afterlife, so should their last act on Earth really be to act the total fucking bastard to minorities and anyone they've not known all their lives?
I know an old guy in my neighbourhood; I once helped him out with a website of his and now I'm stuck with him. He's in his 70s and has loads of extraordinary stories about his countless jobs and japes, and though half of them are no doubt balderdash he's still quite entertaining. He also thinks HIV/AIDS is a disease the 'organism' that is the Earth created to wipe out homosexuality. He fully believes in the death penalty as a way to reduce the prison population. He's also a UKIP activist though I'm sure that's a coincidence.
My grandfather, who I love dearly, has professed clearly racist views in the past and I do everything I can to ensure the conversation goes nowhere near any vaguely related subject. My 72-year-old stepfather is worse. I have a mate who absolutely idolises his ageing father and who I heard use the words 'fucking poofs' the other day, fully imitating his wonderful old man, completely without sarcasm.
There is the odd ray of light. I read about an old gent at Labour's recent party conference who made an impassioned speech in favour of workers' and human rights. My chest swelled with pride, and by all accounts he brought the auditorium close to tears. My pride and their tears were a direct result of the astonished delight that we'd found an old man who wasn't a bigot railing against any form of change and the way 'naive' people below the age of 70 are ruining things for everyone.
The obvious assumption is that old people look back on their lives, realise they've wasted a huge majority of their time in jobs that amounted to bugger all, and set about raging at the injustice of it all. But why exactly they home in on 'progress' as the cause of their unspeakable futility is anyone's guess. Can they honestly believe that the world would be a better place if they'd been allowed to live like the peasants in Monty Python and the Holy Grail, eventually to be carried away on a cart of corpses while pleading "I feel happy! I feel happy!"?
That's where we'd be without progress – the past. In almost every single example anyone could ever provide, the past wasn't a better place. Progress is good. Death is inevitable so, please, take my advice: when you feel the first stirrings of old age tugging at your mind with the words "But why does everything always have to change?", accept that your time is up.
You're no longer relevant to public life in any way, but that's fine, because we'll look after you. We'll reform health and social care so you're cared for properly and with dignity. You can laugh out your final years with your friends and family, protected from frightening current events. And the rest of humanity can get on with the business of tolerance and fairness without you beating us about the brains with your bitterness.
Clacton or Clyde
September 12, 2014 Uncategorizedpolitics, Scotland, UKIPChris
It's too late to cancel the Scottish independence vote now, we'll have to let that go ahead. There's a bi-election on the way as well but I'm not currently focused on whether some skinny Tory tit can beat off a man named Roger in some coastal town filled with people gasping for one last view of the sea before they heave their final decrepit breath.
But people probably think they're going to get a vote in a general election in whatever's left of the UK in May next year. Well, people are wrong, because I've just cancelled it.
I'm afraid it's time the people of this country accepted that a healthy majority, in terms of numbers if not health, do not understand how elections work and therefore shouldn't have the right to elect anything more than the next chairman of John Lewis. And because I despise the upper classes of this country just as much as the imbeciles who vote for whoever Murdoch likes this month, I'm banning the whole process, and declaring myself in charge at the head of a very angry dictatorship.
Scotland are currently trying to work out whether to fuck off by themselves, and whether they should or shouldn't is not for me to say, though obviously they shouldn't. Yet kilted prat after kilted prat has been on my TV in the last couple of weeks saying something like this: "They say we won't be allowed to keep the pound and our economy will go to shit, but to be honest I think they're just scaremongering, so I'm voting 'yes'."
A naked (impressively chested) young lady covered in blood runs shrieking from a cabin in a forest. There's a reasonable chance that there's a madman with an axe in there chopping up her boyfriend, but to be honest I think she's just scaremongering so I think I'll pop my head round the door anyway.
As patiently as I can manage: just because they're saying things to frighten you, it doesn't mean you're not all going to be left bankrupt within a week, tearing each other's hair out for food and fucking the neighbour's guinea pig because 'a need ma hole' before you die screaming. Right now in Aberdeen there are people saying 'we want to rule ourselves we don't want more Tory governments we want democracy wah wah wah' ohhhh Christ, fucking get it through your heads that one day, believe it or not, David Cameron will get old and die and not be Prime Minister any more so using him and his evil chums as a reason to vote for independence is like stockpiling sun loungers and burning all your coats in June.
Meanwhile, in a seaside town in Essex or Kent or Suffolk or wherever the fuck they're all almost dead and therefore love Nigel Farage, there's a bi-election, and a hag was asked by a reporter if she'd vote UKIP. Oh yes, she said. She was then asked if she'd vote UKIP in the next general election. Oh I don't know about that, she said.
My darling, you simply do not understand how these things work, and oh I'm sorry that bell means it's your turn for the crematorium. She brilliantly underlined the mistake most people make in elections: they think their vote is crucial.
It's painful to have to say this to you, but your one single vote makes fuck all difference to anything. Yes, it's important to cast it, to have a say, but it's one vote. One out of many thousands does not a crucial vote make. So might you not just as well vote for who you actually want to be the winner?
Perhaps, just perhaps, you should vote for who you think best represents your views. If everyone did that then, yes, this fucking place might end up with Nick Griffin as Prime Minister but if that's what it takes to break this lunatic idea that we can only vote for a couple of parties because we assume that's what everyone else will do, so fucking be it. When will you people fucking realise that they all start on zero?
In 1997, my first general election, I voted for the Tories. The logic behind that was it seemed clear that Labour were going to win by a huge margin, and that didn't seem healthy for politics (I wanted Labour to win, just not control the world forever more), so I voted for some blue dickhead in a pathetic attempt to balance it up a bit. I've hated that logic ever since.
In every election since, I've voted for the candidate closest to my own views, regardless of party. In the 2008 mayoral election I voted for an independent candidate named Lindsey German and subsequently got blamed, personally, by a mate in the pub for allowing the idiot Johnson to win because I'd not voted for Ken Livingstone.
No-one thinks any more, nobody weighs up pros and cons – they just expel sound at each other. If Scotland go independent, if a town of old people vote UKIP, it's fine so long as they've thought it through rather than react insanely against other people, or base their vote on what other people might do, or what people they don't like have said. Sometimes, a big red button with 'Do Not Press' on it is a detonator.
It's your vote, use it to vote for who you want to win, not for who you think can win, because at the start of a vote everyone can win, and your one single vote does not decide a goddamn thing.
But you won't listen, I know that – so that's it, no more elections. It's vote for me by sending me a postal order or don't vote for anyone from now on. Be it Clacton or Clyde the people of this country are too stupid to be trusted with a vote on anything so I hereby proclaim I am the ruler of you all like you one day knew I would and secretly wanted all along.

redpajama_set_name: RedPajamaCommonCrawl


How would you like to have a golf course in your back yard? At Bocaire Country Club, we've created the dream lifestyle for avid golfers. With no tee times on our truly spectacular course, you'll be able to live the life you've always dreamed of in a community of golfers who are as passionate about the game as you are! While you might be checking out Delray Beach's golfer's dream community, don't make a final decision until you've visited us at Bocaire Country Club.
Our members have dubbed Bocaire Country Club a "golfer's paradise" – and for good reason! We've tailored our boutique country club around the golfing lifestyle. When you live here, you can truly enjoy the activities you love most. With loads of luxurious amenities and some of the best policies in the state, we think you'll find that Bocaire beats even the best golfer's dream community in Delray Beach.
Come and spend a day on the links, and we think you'll be convinced. Our newly renovated course was designed by renowned golf course architect Joe Lee, and it's uniquely suited to players at every level. The developing players in our community find that the course is amazingly user-friendly, providing a fun, relaxing experience without being too difficult. Our best players also find this course to be a phenomenal experience and a healthy challenge.
The course is beautifully designed to take full advantage of the gorgeous tropical landscape. Vibrant green fairways are dotted with sparkling little lakes. Well-bunkered greens present a healthy challenge, as players move from gorgeous par 3s to stunning par 4s.
When you're not out on the links, you may enjoy a bit of practice on our putting greens or driving range. Of course, we're well stocked with all the supplies and equipment you need at our in-house store. There's no need to interrupt a good day of golf because we've got everything you need right here!
So before you choose Delray Beach's golfer's dream community, make sure to visit us at Bocaire Country Club. We think you'll be glad you did!


The #WWHL host is quite the star when he goes out-- according to his BFF John Mayer.
Andy Cohen would be hard to miss in any room, but if you ask his BFF, John Mayer, that's especially true when the duo heads out to paint the town red at a gay bar together. It's a lesson he learned for himself by witnessing the power of Andy take grip on a room full of fellow revelers.
"Andy is the hottest thing going. When I walk in a club with Andy, when you walk in a gay club with Andy Cohen, he is the Beyoncé of that whole [room]," John shared on Watch What Happens Live on Tuesday. "It is unbelievable. I've seen celebrity, and I've seen pull, and I've seen clout, but you have not seen anything like Andy Cohen walking in. Just a shooting gallery."
Check out John and Bob Weir performing in the Clubhouse, below.


Flaherty Sensabaugh Bonasso recently joined the West Virginia Craft Brewers Guild (WVCBG) as an associate member. The WVCBG was founded to be an advocate for the state's community of brewers, and is comprised of member breweries and related organizations, as well as craft beer enthusiasts, from around the State of West Virginia.
The WVCBG includes more than half of West Virginia's licensed breweries and is the industry's primary source for breaking news and information.


text:
30 Common Sayings That Are Actually Terrible Advice
Actually, you should cry over spilt milk.
By Sarah Crow October 25, 2018
By Sarah Crow
By all accounts, English is one of the most complex languages on the planet. It's a tongue peppered with proverbs and idioms that native users hurl around without giving a second thought to the deeper meaning. But often, if you look deeper at the linguistic goings-on of our most common sayings, you'll be surprised to find some insidiously horrific messages.
Before you tell someone not to count their chickens before they roost, or not to put all their eggs in one basket, or not to cry over spilt milk, make sure you're well-acquainted with the proverbs of our time—and why many of them are actually terrible, terrible advice. And for more ways to elevate your own vocabulary, brush up on these 50 Things No Woman Should Ever Say After 50.
"Love is blind."
Sure, you may gloss over a few of your new partner's flaws when you get together, but real love isn't blind—and it shouldn't be. Just because you can see the flaws in another person doesn't mean you're not actually in love, and being a good partner doesn't mean constantly overlooking real problems in your relationship. But, if you want to make certain that things are two-heart-eyes amazing, check out the 15 Signs Your Partner Is Marriage Material.
"A bird in the hand is worth two in the bush."
This commonly-used phrase is generally understood to mean that what you currently have is always worth more than what you could get but have no guarantees about securing. However, it's also a great way of justifying complacency.
While this proverb is certainly applicable in some situations—no, it's probably not wise to leave your wife because a Victoria's Secret model just broke off her engagement—it also seems to say that having a decent thing (perhaps a steady but ultimately unfulfilling job) is better than going after something you truly want and potentially failing. And for more expressions to remove from your personal lexicon, start with these 40 Slang Terms No One Over 40 Should Ever Use.
"You can't make an omelet without breaking some eggs."
In a strict sense, this is true—omelets are literally dependent on the cracking of eggs to be made. However, this phrase, which is used to mean, "You can't create something good without some negative effects occurring," is far from true.
While bad things do happen, they don't always happen—and in many cases, if you can't create a positive outcome without encountering a negative one along the way, the problem isn't the event. It's you. And when you're ready to make your speech sound less dated, it's time to ditch these 40 Things Only Older People Say.
"Don't count your chickens before they hatch."
This phrase means simply that you shouldn't count on a positive outcome before you have evidence of it happening. It's also dreadfully pessimistic. Are we really still telling people that optimism is a bad thing?
"Absence makes the heart grow fonder."
Can a weekend away from your significant other sometimes make you more appreciative of them when you return? Absolutely. However, this isn't always true. Considering how often long-distance relationships fail, it's pretty clear that there are some limitations to this rule. Think that's bad advice? Just wait until you see these 40 Relationship Tips That Are Actually Terrible.
"Why buy the cow when you can get the milk for free?"
This phrase, which generally advises men against marrying women who will sleep with them first, is about as sexist as they come. Considering that research suggests that approximately 95 percent of people have premarital sex, it hardly seems like an applicable saying these days. Oh, and if you ever want to get a date again—or if you just want to be a not-horrible person—never compare women to livestock.
"No pain, no gain."
While this reasonably self-explanatory piece of wisdom is most commonly spouted by the musclebound these days, there are more general contexts in which it's applied, as well. And in general, it's simply not true—while hard work often yields positive results, suffering doesn't have to be part of the package. And if you want the bulk without this inane saying, try out these 40 Great Exercises for Adding Muscle Over 40.
"Curiosity killed the cat."
Meaning that being overly inquisitive can get you in trouble, this phrase is often dropped when people seem to be asking too many questions. However, if you're in the habit of telling people that curiosity is somehow a negative trait, you're definitely in the wrong.
"Don't cry over spilt milk."
"Don't cry over spilt milk" simply means that there's no use fretting about a bad thing if there's no way to fix it. However, it's also a pushy way of telling people that their feelings aren't worthwhile, and a particularly unsympathetic way of suggesting that people move on from traumatic experiences.
"Every cloud has a silver lining."
While "every cloud has a silver lining" may be a nice way of looking at bad situations with some optimism, it's also just not accurate. Sometimes bad things happen, and you only have worse things to look forward to.
"A chain is only as strong as its weakest link"
Though it may seem to make sense that a team would only be as strong as its weakest member, this is pretty much only true if your strongest member isn't doing their job. You may have a coworker who's not up to snuff, but if you have a good leader in charge, they shouldn't bring the whole team down.
"It is what it is."
"It is what it is" might just be the ultimate conversation stopper. It's also one of the more nihilistic ways of looking at the world: If you think that the way things are is the way that they will be indefinitely, what's the use of trying, anyway?
"Better late than never."
In some cases, it is better to do something late than to never do it at all. However, this expression is often used to justify adults making poor choices. Sure, if someone repays a loan late, that's better than never getting your money at all, but it's still pretty inconsiderate. Never be late again; master the 15 Easy Hacks That Will Make You On Time—All The Time.
"The early bird catches the worm."
Though it may be true that some people who act early have better luck in the long run, that's far from an a priori maxim. In fact, being too eager to get something accomplished might just mean you're overlooking important details along the way.
"If it ain't broke, don't fix it."
While it stands to reason that you don't need to fix something until it breaks, this expression is a great excuse for some serious laziness. For instance, while flip phones may have been a fine way of communicating, if nobody had "fixed" things, we'd never have smartphone technology. In fact, trying to make existing inventions better—whether they're already broken or not—is how progress is made.
"Only God can judge me."
Depending on your particular religious beliefs, you may think this is ultimately true. That said, between you and the big man, there are teachers, bosses, police officers, juries, and, you know, actual judges who have every right to make some judgments about you, too.
"Laughter is the best medicine."
This is literally only true for those who've never heard of penicillin. And in many cases, people going through a traumatic situation don't actually want to be cracked up; they want to sit with their current feelings.
"Don't put all your eggs in one basket."
While this phrase, which advises against risking everything on a single opportunity, may make sense if you're considering spending your nest egg on lottery tickets, it's hardly sage advice in general. In many cases, without taking a big risk, you'll never reap big rewards. Just ask virtually any successful entrepreneur.
"If you can't beat 'em, join 'em."
Just because you can't change someone else's opinion or behavior doesn't mean you should change your own. You probably had a good reason for disagreeing with them in the first place, and it's never a good look to back down from your convictions so easily.
"Where there's smoke, there's fire."
"Where there's smoke, there's fire" generally means that, if you hear a rumor, there's at least a grain of truth to it. The only problem? That's not always the case. Just look at any "leaks" from Marvel movie sets.
"Keep your friends close and your enemies closer."
Though you may want to keep an eye on people who seem intent upon doing you harm, there's no real reason for this saying to dictate you into planning your life around paranoia. In fact, unless you're a spy or a particularly scandal-prone politician, most people simply aren't spending that much time thinking about how to outwit you.
"The squeaky wheel gets the grease."
This phrase posits that the most noticeable problems—or the ones most commonly complained about—are the ones most likely to get fixed. However, many also take this to mean that if there's not a glaring error, then everything is fine. Unfortunately, that also means that those who subscribe to this theory are at risk of overlooking smaller issues, and assume that problems will be more obvious if they're worth fixing.
"Beggars can't be choosers."
In a literal sense, if you're begging for something to eat and then suddenly upgrade your request to filet mignon and Veuve Clicquot, you're probably overplaying your hand. However, if you think that anybody who asks for a favor has to accept the bare minimum, you're probably not as generous as you think.
"It's always darkest before the dawn."
It's nice to imagine that the worst moments in our life are followed up by better ones. That said, not only does the darkest part of the night not directly precede the dawn—it's already getting lighter before dawn, technically—in many cases, bad things happen, and then more bad things happen. And then more bad things happen.
"A leopard cannot change its spots."
This phrase, which means a person can't change their nature, is a pretty depressing way to look at life. People make huge changes for the better all the time, and just because you've seen someone's bad side doesn't mean that's all there is to them.
"Be true to yourself."
In theory, this is a nice sentiment: Stand by your convictions. In practice, however, it's not such good advice. What if your true self is horrible? Also, it poses a more philosophical question: should you be true to the self you present to the world, or the one you aspire to be?
"Too many cooks spoil the broth."
While too many cooks in an actual kitchen may make for some difficult meal prep, this phrase also negates the value of diversity. In many cases, having too many ideas to choose from is far better than having too few.
"If you want something done right, you have to do it yourself."
Being a self-starter is great, as is being capable of working independently. If you actually think that nobody can do a job as well as you, though, you're making it pretty clear you're not a team player.
"Money is the root of all evil."
Money can certainly complicate situations. However, claiming that money is the root cause of all of the problems in the world conveniently ignores the countless issues that can't be solved with cash alone. And worse yet, this so-called wisdom is only ever spouted by those who have enough money to get by.
"Good things come to those who wait."
Does patience sometimes pay off? Certainly. Does being patient guarantee that good things will happen? Absolutely not. Many people keep putzing around until their luck rolls in only to realize that they've been waiting in vain. And for some wisdom that's actually worth following, check out these 100 Life-Changing Quotes to Inspire Your Days.
To discover more amazing secrets about living your best life, click here to sign up for our FREE daily newsletter!
5 Things Smart Men Never Say to a Naked Woman
Avoid turning your night of amour into a lingering nightmare.
20 Things She Always Wants You to Say
You can never go wrong with these go-to words and phrases.
20 Things He Always Wants You to Say
And the more often you say it, the better.
50 Lies Kids Say That Parents Always Fall For
"If we get a dog, I promise I'll take care of it!"
The 40 Best Ways to Conquer Your 40s
Your ultimate compendium for thriving in life's best decade.
The 20 Definitive Style Rules for Men Over 40
Cargo shorts need not apply.
The 40 Ways to Master Your 40s
It's your best decade. Own it.
40 Best Dating Tips for Women Over 40
No, it shouldn't feel so daunting.
Study Proves More Sex Can Delay Menopause
Here's why you should be doing it on a weekly basis.
Capt. Sully's Empowering Message About Retiring
"Make your part of the world right, just, good, safe."
15 Valentine's Day Gifts Your Husband Will Love
These thoughtful gifts are sure to make his holiday.
50 Best Marriage Tips of All Time
Use this advice to maintain marital bliss.
These Are the Best Road Trips in the Southwest
Red rocks, stately saguaro cacti, and endless stretches of sand
23 English Words Everyone Mispronounces
Plus, learn how to properly pronounce them.


Here is the taste of winter updated in a stewed fruit compote that uses a V8 V-Fusion juice base, dried fruit, white wine and lemon and vanilla to spice it all up!
dried prunes	 2 lb. 2 qt.
1. In a large saucepan combine dried fruit.
2. Pour juice, wine, lemon zest and vanilla over dried fruit mixture in saucepan; mix well. Place over medium flame on stove top and bring to a simmer; reduce heat and cook, gently, for 35 minutes or until fruit softens and liquids have been partially absorbed and thickened. Remove from heat and keep warm. CCP: May be served hot at 140°F or higher, or chilled to 40°F or lower.
3. To Serve: Serve warm or at room temperature, 1 cup per serving, topped with a #16 scoop (1/4 cup) of vanilla ice cream or frozen yogurt or with a slice of pound cake. Or serve as an accompaniment to roast pork, game, chicken, poultry, etc.
dried prunes	 1.5 lb. 2 qt.


text:
ESSA Title I Services
FranCenter is a 501(c)(3) Not-for-profit Organization
The Sisters of Saint Francis of Joliet, Illinois, and parents were instrumental in the creation and early success of the FranCenter clinic. Sister Lorraine Young served as founding director, Sister Dominic Krivich was co-director and diagnostician, and Sister Patricia Wagner was the clinic's administrator. Dr. Bob Marciante was Executive Director of the clinic from 1983 to the present. He introduced the center's outreach programs which included staff development and training and placing qualified teachers in schools. Today, the center provides teachers in all areas of the curriculum including staff for Title I programs.
The majority of FranCenter staff holds Masters or Doctorate degrees with extensive experience in human behavior and learning. Educational specialists tutor in all areas of the curriculum, while other specialists work with ADD/ADHD, LD, and with students on the autism spectrum. FranCenter works with gifted and talented students to provide enrichment and critical and creative thinking strategies.
The Sister Lorraine Young Scholarship fund was established in 1990 for families needing financial assistance.
The greatest moral obligation of a society is to empower its citizens to grow toward self-actualization by becoming life-long learners and contributing members of the community in which they live. FranCenter believes the most important work on this earth is to help people take responsibility for themselves and for the world in which they live. FranCenter exists to affirm, support and act upon the needs of individuals, families and school systems to develop an educated and responsible citizenry.
FranCenter exists to affirm, support and act upon the needs of individuals, families and school systems to develop an educated and responsible citizenry.
1510 Plainfield Road
Darien, IL 60561
Monday thru Thursday:
© 2021 FranCenter - All Rights Reserved


Reverend Kat ~ the Soulsearch: Unconditional Love – What Could It Mean For You?
Unconditional love – Reverend Kat says, is a fairly simple concept. Yet, we often have blocks to unconditional love.
What could unconditional love mean for you?
Reverend Kat's definition of unconditional love is the following: When you are in the altered state of unconditional love, it means you have no obligations, or expectations. You are free of the need for conditions.
There are many spiritual traditions that help you attain an altered state of consciousness. They do this through daily practices. Chanting, prayer, meditation, walking in nature, music, and poetry are examples of practices that help you clear the chatter from your mind.
Reverend Kat draws from these traditions and helps you understand the process. She recounts wonderful stories and tips on how to achieve the state of unconditional love – an altered state of consciousness!
Think of unconditional love as a spiral – not as a give and take. Love comes back to you.
Listen to Reverend Kat's show for more tips and inspiring true-life experiences from Kat's life!
I began my career as a Spiritual Leader when I was 7 years old. Sitting in the field beside my house one day, I asked God why some people were so unhappy. A real voice answered (no kidding),"Your job on this earth is to teach people about love and how to have what they want in life".
From that day on, I have pursued this with a passion. From my original dream of becoming either a missionary or an actress, I have crafted a career that is grounded in Spirit as I tune into a channel that broadcasts what's in others' hearts and souls.
As a spiritual leader, I teach, write, and perform on life's stage… and, as the voice predicted so long ago, I teach people about love and how to manifest from the heart.
I have faced many challenges in my life including the death of my mother when I was young, being kidnapped as a teenager and leaving a 20 plus year marriage in my 40's. I have learned a ton through the school of hard knocks and delightful surprises as well as the training noted below.
This entry was posted	on Wednesday, November 15th, 2017 at 6:21 am	and is filed under Reverend Kat. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.


text:
Column: The politicizing of Hillary Clinton's…
Column: The politicizing of Hillary Clinton's marriage
Former Secretary of State Hillary Rodham Clinton delivers remarks Jan. 27 to the National Automobile Dealers Association meeting in New Orleans.
By Margaret Carlson |
How responsible is a wife for the betrayal of her husband? In the case of Hillary Clinton, the answer is, a lot, according to Republican National Committee Chairman Reince Priebus and Senator Rand Paul. They got delicious material to use in their effort from exchanges between Clinton and her best friend Diane Blair. Blair died at 61 in 2000. Her husband donated her papers to the University of Arkansas, where they were reviewed by the Washington Free Beacon, a conservative website. The charge against Hillary is that she was an enabler, not a victim, of her husband's extramarital affairs, a long string of which culminated in the White House encounters with Monica Lewinsky. Recalling a 1998 conversation, Blair wrote: 'HRC insists, no matter what people say, it was gross inappropriate behavior but it was consensual (was not a power relationship) and was not sex within real meaning.' As engrossing as it is to get inside Hillary's mind, to use Bill Clinton's behavior against Hillary requires that you think she let the philandering happen, that she somehow deserved it (she's often portrayed as cold and withholding), that she did nothing to stop it, blamed the other woman, and through it all, didn't suffer. Her first reaction about Monica was the one many of us would have: This can't be true; surely, not in the Oval Office (or the adjoining study), surely not with an employee; surely not someone young enough to be his daughter. Then came the second thought: How do I protect Chelsea, calm the rabble hounding us on the front lawn night and day, keep our enemies from using it? What she didn't do was leave. But since when do we punish people for NOT breaking up their marriages? Aren't Republicans the family values folks? And her instinct was to believe her husband above the women with whom he strayed. Who wouldn't? Still these remembrances from Blair show Hillary to be ready to attack women to defend her husband, guilty to all but her. She believed too long, defended too strenuously, and lined up with women's groups who wouldn't ordinarily be siding with a public official who treated women so badly. The most damaging to her is that it wasn't just aides such as Sidney Blumenthal who described Monica as a crazed spurned groupie as she stormed the Northwest gate, waiting in the pouring rain to be admitted. It is chilling to read Blair's telling of how Hillary damned Lewinsky as a 'narcissistic loony tune,' even after she knew the intern was telling the truth. Even worse, when it wasn't Hillary's marriage imperiled and in the cool light of day, she takes after 'whiny women' who were (rightly) accusing Democratic Sen. Bob Packwood of sexual aggression. Her reaction is knee-jerk, and she is looking out for the support in Congress for her health-care effort, not the young girls Packwood went after. This plays into the assessment of Clinton's own pollsters that while Bill came across as slick, she came across much worse, as 'too politically ambitious, too strong, and too ruthless.' There's a lot to read in Blair's papers, aside from the R-rated. The inner thoughts of the Clintons are on display as they found themselves in the crucible of Washington, a foreign country that surprised them with its hostility. Ever since Bill Clinton 'took office they've been going thru personal tragedy ([the death of] Vince [Foster], her dad, his mom) and immediately all the ugly forces started making up hateful things about them, pounding on them.' As with most things Hillary, her behavior and the reaction of those who would defend her is as mixed as is she, a combination of Lady Macbeth and a Methodist Mother Teresa gathering up a village to save the world. There is a lot here to damn Hillary for as she combined wife, mother and first lady to deal with the perfidy of her husband with no privacy (she didn't even have that with Blair) and a cracked, if not broken, heart. Before Republicans go full hog on this tack they might recall two things. One is that Hillary's poll numbers were in low single digits before Monica and but for Monica might not have risen enough for her to run for, and win, a Senate seat in New York. The other is that sometimes the messenger gets tarred by the message. Margaret Carlson is a Bloomberg View columnist.
Margaret Carlson
From the drawing board


Wargaming today announced that their popular free-to-play tank warfare game, World of Tanks, will soon be coming to the Xbox One console.
Yes, World of Tanks on Xbox One will support cross-platform play.
You'll be able to play World of Tanks against tankers on both Xbox 360 and Xbox One at release! This means commanders on Xbox 360 and Xbox One will go head-to-head on the same battlefields. But all that high-explosive, metal-smashing, steel-on-steel combat that you know and love will look oh so nice on your Xbox One.
Yes, your hard-earned progress comes with you to Xbox One.
Because your progress is connected to your Xbox Live account, all your progress including vehicles, Experience, Credits, Gold and items that you've fought hard to earn will come with you to Xbox One, so long as you're using the same account!
Cross platform play AND I get to keep my progress? Sign me up! To hold you over until launch, here's a batch of screens showcasing the visuals of the Xbox One version.


text:
What We Offer Breadcrumb Separator
Activities Breadcrumb Separator
Wandsworth Heritage Service
Step Back in Time at Your Local Heritage Service
Your local archives hold unique and vital records that underpin education, heritage, business and identity. Visiting an archive can take you on an adventure – you may end up discovering much more than you imagined.
Archives are full of fascinating content to read, touch and explore. You'll discover the stories, the facts, the places and the people that are at the heart of our community. No matter what you're looking for, there will be something to inspire you.
Without archives, we wouldn't know if this summer is the 'hottest on record', we wouldn't have such historically rich novels and films, we wouldn't know about the lives of our significant artists, and we wouldn't be able to revisit controversial and compelling legal cases from years gone by.
Using the Heritage Service
Staff at our locations will be there to help with any questions and get you started with your research. There are guidelines for using any Heritage material below, these are to make sure that original and unique material is kept safe for future generations. You can take notes on a laptop or tablet but please be aware that we have limited facilities for charging these so it is best to have a full battery. We also have paper and pencils available for taking notes.
Research guides for our collections are available below, and staff will help to point you in the right direction. Historical research can sometimes be very time-consuming and it is not always possible to find the exact information you want – records were not always kept or created as we might like, so be prepared to spend a bit of time on your research. It is also useful to bring any notes or information you already have so you can check the details.
About Our Historical Archives
We hold records back to 1489, a wide range of books and articles on London borough's history and hundreds of old newspapers, maps and census returns.
Records include:
Local organisations, such as political parties, debating societies and sports clubs
Local businesses, including material relating to Morgan Crucible, the builders T H Adamson and local shops
Local people, including family correspondence covering everyday life from the 19th century onwards, letters home from all over the world and from the trenches in the First World War, love letters, business letters and diaries of a range of local people
Civil parishes, which were predecessors of the borough councils, including minutes and accounts from the 16th century onwards, records of the workhouses before 1834 and rate books
School records for Church of England schools in the borough, including admission registers and log books
Building plans, including drainage applications which had to be submitted when new properties were built.
Archives catalogue
Searchroom Guidelines
Please follow these guidelines to ensure the preservation of fragile and unique documents and the safety of your belongings:
Take care when handling archives – ask for advice
Secure bags and coats in a locker
Use pencils and laptops only when making notes – no pens
Do not bring food or drink into the searchroom – no eating or drinking is allowed
Ask staff before photographing or photocopying any material. Staff will advise on the purchase of photograph permits or the suitability of photocopying
Online Historical Resources
Local history and heritage: A dramatic walk through Putney (circa 1908)
Heritage and local history family resources
Heritage service strategy for archives and local history
Heritage service policies and terms of reference
Tooting Common heritage project


The Department of Energy (DoE) has awarded a $1 million grant to QBotix to enhance the company's robotic system for optimizing the energy output and efficiency of solar panels. The funding for the Menlo Park, Calif.-based company, which has developed a monorail system of robots for tilting panels toward the sun, is part of the DoE's SunShot Incubator Program.
The program is a national effort to make solar competitive with other forms of electricity in the US by the end of the decade. The funding was part of $10 million in grants awarded to innovative solar projects as part of the program, according to the DoE.
The QBotix Tracking System is the first comprehensive and intelligent system to use robots to automate solar-panel tracking, reducing the electricity requirement of the system by 20 percent while increasing the output of the panels by up to 15 percent, according to the company.
QBotix plans to use the funding not only to improve its existing technology, but also to advance the technology to support what's called concentrated photovoltaics (CVP), Michael Kanellos, a QBotix spokesman, told Design News.
Currently, the robotic system works like typical trackers, tilting the panels toward the sun about once every 40 minutes as the sun moves. A CVP system, however, tilts the panels so all of the available sunlight at any given time will hit the panel directly, he said. "So it's not just the sun, it's like having 200 or 300 suns powering the panels," Kanellos told us. To support CVP, QBotix must enhance its robotic system to tilt the panels faster, at a rate about once every five minutes, he said.
QBotix also will use the money to fund more demonstrations of the system to prove how it can change the game for the management of solar-energy systems. "Solar is a very conservative industry," Kanellos said. "Everybody likes the idea but is hesitant to invest. The more data we have, the better."
QBotix currently runs its own demonstration of the robotic tracking system, with another up and running at a facility owned by Sol Orchard, a solar power plant developer based in Carmel, Calif.
The company is expected to name another major customer in January, when the QBotix Tracking System will help manage a complete solar power plant built for a municipal government agency, Kanellos added. He declined to name the agency or municipality.
The award from the DoE shows the government sees the bigger picture in terms of making solar more viable, as much of the focus until now has been making solar panels themselves less expensive and more efficient rather than investing in what is called the "balance of systems," Kanellos said. This term refers to the other technology like trackers that make an entire solar-power system work, or "everything but the solar panel," he said.
While solar panels themselves are relatively inexpensive and efficient, the technology around them in a solar-energy system now costs 67 percent of the entire deployment, Kanellos said. "It's good to see that researchers and other companies are seeing the importance of the balance of systems in solar development," he said.