text:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <ListInstance
    Title="Products"
    OnQuickLaunch="TRUE"
    TemplateType="10987"
    Url="Lists/Products"
    Description="Wingtip Products List">
    <Data>
      <Rows>
        <Row>
          <Field Name="Title">Batman Action Figure</Field>
          <Field Name="ProductCode">WP0001</Field>
          <Field Name="ProductDescription">A super hero who sometimes plays the role of a dark knight.</Field>
          <Field Name="ProductListPrice">14.9500000000000</Field>
          <Field Name="ProductColor">;#Black;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0001.jpg, Batman Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Captain America Action Figure</Field>
          <Field Name="ProductCode">WP0002</Field>
          <Field Name="ProductDescription">A super action figure that protects freedom and the American way of life.</Field>
          <Field Name="ProductListPrice">12.95</Field>
          <Field Name="ProductColor">;#Red;#White;#Blue;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0002.jpg, Captain America Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">GI Joe Action Figure</Field>
          <Field Name="ProductCode">WP0003</Field>
          <Field Name="ProductDescription">A classic action figure from the 1970s.</Field>
          <Field Name="ProductListPrice">14.95</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0003.jpg, GI Joe Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Green Hulk Action Figure</Field>
          <Field Name="ProductCode">WP0004</Field>
          <Field Name="ProductDescription">An overly muscular action figure that strips naked when angry.</Field>
          <Field Name="ProductListPrice">9.99</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0004.jpg, Green Hulk Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Red Hulk Alter Ego Action Figure</Field>
          <Field Name="ProductCode">WP0005</Field>
          <Field Name="ProductDescription">A case of anabolic steroids with a most unfortunate outcome.</Field>
          <Field Name="ProductListPrice">9.99</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0005.jpg, Red Hulk Alter Ego Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Godzilla Action Figure</Field>
          <Field Name="ProductCode">WP0006</Field>
          <Field Name="ProductDescription">The classic and adorable action figure from those old Japanese movies.</Field>
          <Field Name="ProductListPrice">19.95</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0006.jpg, Godzilla Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Perry the Platypus Action Figure</Field>
          <Field Name="ProductCode">WP0007</Field>
          <Field Name="ProductDescription">A platypus who plays an overly intelligent detective sleuth on TV.</Field>
          <Field Name="ProductListPrice">21.95</Field>
          <Field Name="ProductColor">;#Green;#Yellow;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0007.jpg, Perry the Platypus Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Green Angry Bird Action Figure</Field>
          <Field Name="ProductCode">WP0008</Field>
          <Field Name="ProductDescription">A funny looking green bird that really hates pigs.</Field>
          <Field Name="ProductListPrice">4.95</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0008.jpg, Green Angry Bird Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Red Angry Bird Action Figure</Field>
          <Field Name="ProductCode">WP0009</Field>
          <Field Name="ProductDescription">A funny looking red bird that also hates pigs.</Field>
          <Field Name="ProductListPrice">4.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0009.jpg, Red Angry Bird Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Phineas and Ferb Action Figure Set</Field>
          <Field Name="ProductCode">WP0010</Field>
          <Field Name="ProductDescription">The dynamic duo of the younger generation.</Field>
          <Field Name="ProductListPrice">19.95</Field>
          <Field Name="ProductColor">;#Green;#Red;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0010.jpg, Phineas and Ferb Action Figure Set</Field>
        </Row>
        <Row>
          <Field Name="Title">Black Power Ranger Action Figure</Field>
          <Field Name="ProductCode">WP0011</Field>
          <Field Name="ProductDescription">A particularly violent action figure for violent children.</Field>
          <Field Name="ProductListPrice">7.50</Field>
          <Field Name="ProductColor">;#Black;#White;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0011.jpg, Black Power Ranger Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Woody Action Figure</Field>
          <Field Name="ProductCode">WP0012</Field>
          <Field Name="ProductDescription">The lovable, soft-spoken cowboy from Toy Story.</Field>
          <Field Name="ProductListPrice">9.95</Field>
          <Field Name="ProductColor">;#Blue;#Yellow;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0012.jpg, Woody Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Spiderman Action Figure</Field>
          <Field Name="ProductCode">WP0013</Field>
          <Field Name="ProductDescription">The classic superhero who is quite the swinger.</Field>
          <Field Name="ProductListPrice">12.95</Field>
          <Field Name="ProductColor">;#Red;#Blue;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0013.jpg, Spiderman Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Twitter Follower Action Figure</Field>
          <Field Name="ProductCode">WP0014</Field>
          <Field Name="ProductDescription">An inexpensive action figure you can never have too many of.</Field>
          <Field Name="ProductListPrice">1.00</Field>
          <Field Name="ProductColor">;#Yellow;#Blue;#</Field>
          <Field Name="ProductCategory">Action Figures</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0014.jpg, Twitter Follower Action Figure</Field>
        </Row>
        <Row>
          <Field Name="Title">Crayloa Crayon Set</Field>
          <Field Name="ProductCode">WP0015</Field>
          <Field Name="ProductDescription">A very fun set of crayons in every color.</Field>
          <Field Name="ProductListPrice">2.49</Field>
          <Field Name="ProductColor">;#Blue;#Red;#Green;#Yellow;#</Field>
          <Field Name="ProductCategory">Arts and Crafts</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0015.jpg, Crayloa Crayon Set</Field>
        </Row>
        <Row>
          <Field Name="Title">Sponge Bob Coloring Book</Field>
          <Field Name="ProductCode">WP0016</Field>
          <Field Name="ProductDescription">An action figure drawing book with America's most recognizable celebrity.</Field>
          <Field Name="ProductListPrice">2.95</Field>
          <Field Name="ProductColor">;#Yellow;#</Field>
          <Field Name="ProductCategory">Arts and Crafts</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0016.jpg, Sponge Bob Coloring Book</Field>
        </Row>
        <Row>
          <Field Name="Title">Easel with Supply Trays</Field>
          <Field Name="ProductCode">WP0017</Field>
          <Field Name="ProductDescription">A serious easel for serious young artists.</Field>
          <Field Name="ProductListPrice">49.95</Field>
          <Field Name="ProductColor">;#White;#</Field>
          <Field Name="ProductCategory">Arts and Crafts</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0017.jpg, Easel with Supply Trays</Field>
        </Row>
        <Row>
          <Field Name="Title">Crate o' Crayons</Field>
          <Field Name="ProductCode">WP0018</Field>
          <Field Name="ProductDescription">More crayons that you can shake a stick at.</Field>
          <Field Name="ProductListPrice">14.95</Field>
          <Field Name="ProductColor">;#Blue;#Red;#Green;#Yellow;#</Field>
          <Field Name="ProductCategory">Arts and Crafts</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0018.jpg, Crate o' Crayons</Field>
        </Row>
        <Row>
          <Field Name="Title">Etch A Sketch</Field>
          <Field Name="ProductCode">WP0019</Field>
          <Field Name="ProductDescription">A strategic planning tool for the Romney campaign.</Field>
          <Field Name="ProductListPrice">12.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Arts and Crafts</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0019.jpg, Etch A Sketch</Field>
        </Row>
        <Row>
          <Field Name="Title">Green Hornet</Field>
          <Field Name="ProductCode">WP0020</Field>
          <Field Name="ProductDescription">A fast car for crusin' the strip at night.</Field>
          <Field Name="ProductListPrice">24.95</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0020.jpg, Green Hornet</Field>
        </Row>
        <Row>
          <Field Name="Title">Red Wacky Stud Bumper</Field>
          <Field Name="ProductCode">WP0021</Field>
          <Field Name="ProductDescription">A great little vehicle for off road fun.</Field>
          <Field Name="ProductListPrice">21.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0021.jpg, Red Wacky Stud Bumper</Field>
        </Row>
        <Row>
          <Field Name="Title">Red Stomper Bully</Field>
          <Field Name="ProductCode">WP0022</Field>
          <Field Name="ProductDescription">A great toy that can crush and destroy all your other toys.</Field>
          <Field Name="ProductListPrice">29.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0022.jpg, Red Stomper Bully</Field>
        </Row>
        <Row>
          <Field Name="Title">Green Stomper Bully</Field>
          <Field Name="ProductCode">WP0023</Field>
          <Field Name="ProductDescription">A green alternative to crush and destroy the Red Stomper Bully.</Field>
          <Field Name="ProductListPrice">24.95</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0023.jpg, Green Stomper Bully</Field>
        </Row>
        <Row>
          <Field Name="Title">Indy Race Car</Field>
          <Field Name="ProductCode">WP0024</Field>
          <Field Name="ProductDescription">The fastest remote control race car on the market today.</Field>
          <Field Name="ProductListPrice">19.95</Field>
          <Field Name="ProductColor">;#Black;#  </Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0024.jpg, Indy Race Car</Field>
        </Row>
        <Row>
          <Field Name="Title">Turbo-boost Speedboat</Field>
          <Field Name="ProductCode">WP0025</Field>
          <Field Name="ProductDescription">The preferred water vehicle of gun runners and drug kingpins.</Field>
          <Field Name="ProductListPrice">32.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0025.jpg, Turbo-boost Speedboat</Field>
        </Row>
        <Row>
          <Field Name="Title">Sandpiper Prop Plane</Field>
          <Field Name="ProductCode">WP0026</Field>
          <Field Name="ProductDescription">A simple RC prop plane for younger pilots.</Field>
          <Field Name="ProductListPrice">24.95</Field>
          <Field Name="ProductColor">;#White;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0026.jpg, Sandpiper Prop Plane</Field>
        </Row>
        <Row>
          <Field Name="Title">Flying Badger</Field>
          <Field Name="ProductCode">WP0027</Field>
          <Field Name="ProductDescription">A tough fighter plane to root out evil anywhere it lives.</Field>
          <Field Name="ProductListPrice">27.95</Field>
          <Field Name="ProductColor">;#Blue;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0027.jpg, Flying Badger</Field>
        </Row>
        <Row>
          <Field Name="Title">Red Barron von Richthofen</Field>
          <Field Name="ProductCode">WP0028</Field>
          <Field Name="ProductDescription">A classic RC plane to hunt down and terminate Snoopy.</Field>
          <Field Name="ProductListPrice">32.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0028.jpg, Red Barron von Richthofen</Field>
        </Row>
        <Row>
          <Field Name="Title">Flying Squirrel</Field>
          <Field Name="ProductCode">WP0029</Field>
          <Field Name="ProductDescription">A stealthy remote control plane that flies on the down-low and under the radar.</Field>
          <Field Name="ProductListPrice">69.95</Field>
          <Field Name="ProductColor">;#Grey;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0029.jpg, Flying Squirrel</Field>
        </Row>
        <Row>
          <Field Name="Title">FOX News Chopper</Field>
          <Field Name="ProductCode">WP0030</Field>
          <Field Name="ProductDescription">A news chopper which can generate fabricated news events on demand.</Field>
          <Field Name="ProductListPrice">29.95</Field>
          <Field Name="ProductColor">;#Blue;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0030.jpg, FOX News Chopper</Field>
        </Row>
        <Row>
          <Field Name="Title">Seal Team 6 Helicopter</Field>
          <Field Name="ProductCode">WP0031</Field>
          <Field Name="ProductDescription">A serious helicopter that can open up a can of whoop-ass when required.</Field>
          <Field Name="ProductListPrice">59.95</Field>
          <Field Name="ProductColor">;#Green;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0031.jpg, Seal Team 6 Helicopter</Field>
        </Row>
        <Row>
          <Field Name="Title">Personal Commuter Chopper</Field>
          <Field Name="ProductCode">WP0032</Field>
          <Field Name="ProductDescription">partially-test remote control device that can actually carry real people.</Field>
          <Field Name="ProductListPrice">99.95</Field>
          <Field Name="ProductColor">;#Red;#</Field>
          <Field Name="ProductCategory">Vehicles and RC</Field>
          <Field Name="ProductImageUrl">/ProductManager/ProductImages/WP0032.jpg, Personal Commuter Chopper</Field>
        </Row>
      </Rows>
    </Data>
  </ListInstance>
</Elements>


text:
texfigure: Python Helpers for PythonTeX
---------------------------------------

texfigure is a package designed to make it easier to work with matplotlib and
other figures inside PythonTeX documents.

.. toctree::
  manager

.. automodapi:: texfigure

redpajama_set_name: RedPajamaGithub


text:
const { resolve } = require('path')
const nj = require('koa2-nunjucks')
module.exports = function() {
  return nj({
    // debug: true,
    ext: 'html',
    path: resolve('./html'),
    njConfig: {
      watch: true
    }
  })
}


text:
This is an Authentication API server using Node.js and PostgreSQL for data storage. It uses Redis & JWT for session management.

## Requirements
Docker

[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)

## Installation

`make build-dev`

## Usage

`make up-dev`

- Run database migrations & seeds:

`npm run faker`

`npm run migrate`

`npm run seed`

- Access Swagger-UI
[http://localhost:8080](http://localhost:8080)

## Tests

`make test`

## Maintainers

[sgraham785](https://github.com/sgraham785)

## Contributing

1. Create your feature branch: `git checkout -b my-new-feature`
2. Commit your changes: `git commit -am 'Add some feature'`
3. Push to the branch: `git push origin my-new-feature`
4. Submit a pull/merge request to a maintainer :D

## Roadmap
in no particular order

- [x] Decalative routes
- [x] Public vs. Private(auth) routes
- [x] Migrations & Seeds
- [x] Add security best practices
- [x] Password encryption
- [x] Use JWT for private route auth
- [x] Create Postman collection
- [x] Verification emailer
- [x] Use faker for seeding
- [x] Utilize swagger documentation
- [x] Dockerize
- [x] SSL
- [x] Health check
- [ ] Add tests

## Known Issues
* https://github.com/sgraham785/node-postgres-api-server/issues


text:
import React from 'react';
import {connect} from 'react-redux';
import {goFetchForums, compareRepo} from '../redux/actions/';

const Stage = props =>
  <div className="root-wrapper">
    { props.UI.forumsFetched ?
      <button>Compare!</button> :
      <button onClick={()=>props.goFetchForums()}>Fetch Forums!</button>
    }
  </div>;

const mapStateToProps = state => state;

const mapDispatchToState = dispatch => ({
  goFetchForums() {goFetchForums(dispatch);},
  compareRepo() {compareRepo(dispatch);}
});

export default connect(mapStateToProps, mapDispatchToState)(Stage);


text:
using namespace std;
using namespace rapidjson;

void ipdb::MetaData::Parse(const string &json) {
    Document d;
    d.Parse(json.c_str());
    Build = d["build"].GetUint64();
    IPVersion = static_cast<uint16_t>(d["ip_version"].GetUint());
    NodeCount = d["node_count"].GetInt();
    TotalSize = d["total_size"].GetInt();
    auto fields = d["fields"].GetArray();
    for (auto &field : fields) {
        Fields.emplace_back(field.GetString());
    }
    auto languages = d["languages"].GetObject();
    for (auto &language:languages) {
        Languages[language.name.GetString()] = language.value.GetInt();
    }
}

int ipdb::Reader::readNode(int node, int index) const {
    auto off = node * 8 + index * 4;
    return ntohl(static_cast<uint32_t>(*(int *) &data.get()[off]));
}

string ipdb::Reader::resolve(int node) {
    auto resolved = node - meta.NodeCount + meta.NodeCount * 8;
    if (resolved >= fileSize) {
        throw ErrDatabaseError;
    }
    auto size = (data.get()[resolved] << 8) | data.get()[resolved + 1];
    if ((resolved + 2 + size) > dataSize) {
        throw ErrDatabaseError;
    }
    string bytes = (const char *) data.get() + resolved + 2;
    return bytes;
}

int ipdb::Reader::search(const u_char *ip, int bitCount) const {
    int node = 0;
    if (bitCount == 32) {
        node = v4offset;
    } else {
        node = 0;
    }
    for (auto i = 0; i < bitCount; ++i) {
        if (node > meta.NodeCount) {
            break;
        }
        node = readNode(node, ((0xFF & int(ip[i >> 3])) >> uint(7 - (i % 8))) & 1);
    }
    if (node > meta.NodeCount) {
        return node;
    }
    throw ErrDataNotExists;
}

string ipdb::Reader::find0(const string &addr) {
    int node = 0;
    struct in_addr addr4{};
    struct in6_addr addr6{};
    if (inet_pton(AF_INET, addr.c_str(), &addr4)) {
        if (!IsIPv4Support()) {
            throw ErrNoSupportIPv4;
        }
        node = search((const u_char *) &addr4.s_addr, 32);
    } else if (inet_pton(AF_INET6, addr.c_str(), &addr6)) {
        if (!IsIPv6Support()) {
            throw ErrNoSupportIPv6;
        }
        node = search((const u_char *) &addr6.s6_addr, 128);
    } else {
        throw ErrIPFormat;
    }
    auto body = resolve(node);
    return body;
}

vector<string> split(const string &s, const string &sp) {
    vector<string> output;
    string::size_type prev_pos = 0, pos = 0;
    while ((pos = s.find(sp, pos)) != string::npos) {
        string substring(s.substr(prev_pos, pos - prev_pos));
        output.emplace_back(substring);
        prev_pos = ++pos;
    }
    output.emplace_back(s.substr(prev_pos, pos - prev_pos)); // Last word
    return output;
}

vector<string> ipdb::Reader::find1(const string &addr, const string &language) {
    if (meta.Languages.find(language) == meta.Languages.end()) {
        throw ErrNoSupportLanguage;
    }
    auto off = meta.Languages[language];
    auto body = find0(addr);
    auto tmp = split(body, "\t");
    if (off + meta.Fields.size() > tmp.size()) {
        throw ErrDatabaseError;
    }
    vector<string> result;
    for (auto i = tmp.begin() + off; i != tmp.begin() + off + meta.Fields.size(); ++i) {
        result.emplace_back(*i);
    }
    return result;
}

map<string, string> ipdb::Reader::FindMap(const string &addr, const string &language) {
    auto res = find1(addr, language);
    map<string, string> info;
    auto k = 0;
    for (auto &v : res) {
        info[meta.Fields[k++]] = v;
    }
    return info;
}

vector<string> ipdb::Reader::Find(const string &addr, const string &language) {
    return find1(addr, language);
}

bool ipdb::Reader::IsIPv6Support() const {
    return (meta.IPVersion & IPv6) == IPv6;
}

bool ipdb::Reader::IsIPv4Support() const {
    return (meta.IPVersion & IPv4) == IPv4;
}

ipdb::Reader::Reader(const string &file) {
    ifstream fs(file, ios::binary | ios::in);
    if (fs.tellg() == -1) {
        throw ErrFileSize;
    }
    fs.seekg(0, ios::end);
    auto fsize = fs.tellg();
    uint32_t metaLength = 0ul;
    fs.seekg(0, ios::beg);
    fs.read((char *) &metaLength, 4);
    metaLength = ntohl(metaLength);
    string bb;
    bb.resize(metaLength);
    fs.read(&bb[0], metaLength);
    meta.Parse(bb);
    if (meta.Languages.empty() || meta.Fields.empty()) {
        throw ErrMetaData;
    }
    if (fsize != (4 + metaLength + meta.TotalSize)) {
        throw ErrFileSize;
    }
    fileSize = (int) fsize;
    auto dataLen = (int) fsize - 4 - metaLength;
    data = shared_ptr<u_char>(new u_char[dataLen], std::default_delete<u_char[]>());;
    fs.read((char *) data.get(), dataLen);
    dataSize = dataLen;
    auto node = 0;
    for (auto i = 0; i < 96 && node < meta.NodeCount; ++i) {
        if (i >= 80) {
            node = readNode(node, 1);
        } else {
            node = readNode(node, 0);
        }
    }
    v4offset = node;
}

ipdb::Reader::~Reader() = default;

uint64_t ipdb::Reader::BuildTime() const {
    return meta.Build;
}

vector<string> ipdb::Reader::Languages() {
    vector<string> ls;
    for (const auto &i:meta.Languages) {
        ls.emplace_back(i.first);
    }
    return ls;
}

vector<string> ipdb::Reader::Fields() const {
    return meta.Fields;
}

ipdb::ASNInfo::ASNInfo(const vector<string> &data, const vector<string> &fields) {
    auto i = fields.begin();
    auto j = data.begin();
    for (; i != fields.end() && j != data.end(); ++i, ++j) {
        if (*i == "asn")asn = *j;
        else if (*i == "reg")reg = *j;
        else if (*i == "cc")cc = *j;
        else if (*i == "net")net = *j;
        else if (*i == "org")org = *j;
        else if (*i == "type")type = *j;
        else if (*i == "domain")domain = *j;
    }
}

string ipdb::ASNInfo::GetAsn() { return asn; }

string ipdb::ASNInfo::GetReg() { return reg; }

string ipdb::ASNInfo::GetCc() { return cc; }

string ipdb::ASNInfo::GetNet() { return net; }

string ipdb::ASNInfo::GetOrg() { return org; }

string ipdb::ASNInfo::GetType() { return type; }

string ipdb::ASNInfo::GetDomain() { return domain; }

string ipdb::ASNInfo::str() {
    stringstream sb;
    sb << "asn: " << asn << endl;
    sb << "reg: " << reg << endl;
    sb << "cc: " << cc << endl;
    sb << "net: " << net << endl;
    sb << "org: " << org << endl;
    sb << "type: " << type << endl;
    sb << "domain: " << domain << endl;
    return sb.str();
}

ipdb::CityInfo::CityInfo(const vector<string> &data, const vector<string> &fields) {
    auto i = fields.begin();
    auto j = data.begin();
    for (; i != fields.end() && j != data.end(); ++i, ++j) {
        if (*i == "country_name") { country_name = *j; }
        else if (*i == "region_name") { region_name = *j; }
        else if (*i == "city_name") { city_name = *j; }
        else if (*i == "owner_domain") { owner_domain = *j; }
        else if (*i == "isp_domain") { isp_domain = *j; }
        else if (*i == "latitude") { latitude = *j; }
        else if (*i == "longitude") { longitude = *j; }
        else if (*i == "timezone") { timezone = *j; }
        else if (*i == "utc_offset") { utc_offset = *j; }
        else if (*i == "china_admin_code") { china_admin_code = *j; }
        else if (*i == "idd_code") { idd_code = *j; }
        else if (*i == "country_code") { country_code = *j; }
        else if (*i == "continent_code") { continent_code = *j; }
        else if (*i == "idc") { idc = *j; }
        else if (*i == "base_station") { base_station = *j; }
        else if (*i == "country_code3") { country_code3 = *j; }
        else if (*i == "european_union") { european_union = *j; }
        else if (*i == "currency_code") { currency_code = *j; }
        else if (*i == "currency_name") { currency_name = *j; }
        else if (*i == "anycast") { anycast = *j; }
        else if (*i == "line") { line = *j; }
        else if (*i == "district_info") {
            vector<string> names;
            vector<string> values;
            if (!j->empty()) {
                Document doc;
                doc.Parse(j->c_str());
                if (doc.IsObject()) {
                    for (const auto &o: doc.GetObject()) {
                        values.emplace_back(o.name.GetString());
                        names.emplace_back(o.value.GetString());
                    }
                }
            }
            district_info = make_shared<ipdb::DistrictInfo>(names, values);
        } else if (*i == "route") { route = *j; }
        else if (*i == "asn") { asn = *j; }
        else if (*i == "asn_info") {
            vector<shared_ptr<ipdb::ASNInfo>> ans_vector;
            if (!j->empty()) {
                Document doc;
                doc.Parse(j->c_str());
                if (doc.IsObject()) {
                    for (const auto &array:doc.GetArray()) {
                        vector<string> names;
                        vector<string> values;
                        for (const auto &o:array.GetObject()) {
                            values.emplace_back(o.name.GetString());
                            names.emplace_back(o.value.GetString());
                        }
                        ans_vector.emplace_back(make_shared<ipdb::ASNInfo>(names, values));
                    }
                }
            }
            asn_info = move(ans_vector);
        } else if (*i == "area_code") { area_code = *j; }
        else if (*i == "usage_type") { usage_type = *j; }
    }
}

string ipdb::CityInfo::GetCountryName() { return country_name; }

string ipdb::CityInfo::GetRegionName() { return region_name; }

string ipdb::CityInfo::GetCityName() { return city_name; }

string ipdb::CityInfo::GetOwnerDomain() { return owner_domain; }

string ipdb::CityInfo::GetIspDomain() { return isp_domain; }

string ipdb::CityInfo::GetLatitude() { return latitude; }

string ipdb::CityInfo::GetLongitude() { return longitude; }

string ipdb::CityInfo::GetTimezone() { return timezone; }

string ipdb::CityInfo::GetUtcOffset() { return utc_offset; }

string ipdb::CityInfo::GetChinaAdminCode() { return china_admin_code; }

string ipdb::CityInfo::GetIddCode() { return idd_code; }

string ipdb::CityInfo::GetCountryCode() { return country_code; }

string ipdb::CityInfo::GetContinentCode() { return continent_code; }

string ipdb::CityInfo::GetIDC() { return idc; }

string ipdb::CityInfo::GetBaseStation() { return base_station; }

string ipdb::CityInfo::GetCountryCode3() { return country_code3; }

string ipdb::CityInfo::GetEuropeanUnion() { return european_union; }

string ipdb::CityInfo::GetCurrencyCode() { return currency_code; }

string ipdb::CityInfo::GetCurrencyName() { return currency_name; }

string ipdb::CityInfo::GetAnycast() { return anycast; }

string ipdb::CityInfo::GetLine() { return line; }

shared_ptr<ipdb::DistrictInfo> ipdb::CityInfo::GetDistrictInfo() { return district_info; }

string ipdb::CityInfo::GetRoute() { return route; }

string ipdb::CityInfo::GetASN() { return asn; }

vector<shared_ptr<ipdb::ASNInfo>> ipdb::CityInfo::GetASNInfo() { return asn_info; }

string ipdb::CityInfo::GetAreaCode() { return area_code; }

string ipdb::CityInfo::GetUsageType() { return usage_type; }

string ipdb::CityInfo::str() {
    stringstream sb;
    sb << "country_name: " << country_name << endl;
    sb << "region_name: " << region_name << endl;
    sb << "city_name: " << city_name << endl;
    sb << "owner_domain: " << owner_domain << endl;
    sb << "isp_domain: " << isp_domain << endl;
    sb << "latitude: " << latitude << endl;
    sb << "longitude: " << longitude << endl;
    sb << "timezone: " << timezone << endl;
    sb << "utc_offset: " << utc_offset << endl;
    sb << "china_admin_code: " << china_admin_code << endl;
    sb << "idd_code: " << idd_code << endl;
    sb << "country_code: " << country_code << endl;
    sb << "continent_code: " << continent_code << endl;
    sb << "idc: " << idc << endl;
    sb << "base_station: " << base_station << endl;
    sb << "country_code3: " << country_code3 << endl;
    sb << "european_union: " << european_union << endl;
    sb << "currency_code: " << currency_code << endl;
    sb << "currency_name: " << currency_name << endl;
    sb << "anycast: " << anycast << endl;
    sb << "line: " << line << endl;
    if (district_info) sb << "district_info: " << district_info->str() << endl;
    sb << "route: " << route << endl;
    sb << "asn: " << asn << endl;
    for (const auto &i:asn_info)
        sb << "asn_info: " << i->str() << endl;
    sb << "area_code: " << area_code << endl;
    sb << "usage_type: " << usage_type << endl;
    return sb.str();
}

ipdb::City::City(const string &file) : Reader(file) {}

ipdb::CityInfo ipdb::City::FindInfo(const string &addr, const string &language) {
    return CityInfo(Find(addr, language), this->Fields());
}

ipdb::BaseStationInfo::BaseStationInfo(const vector<string> &data, const vector<string> &fields) {
    auto i = fields.begin();
    auto j = data.begin();
    for (; i != fields.end() && j != data.end(); ++i, ++j) {
        if (*i == "country_name") { country_name = *j; }
        else if (*i == "region_name") { region_name = *j; }
        else if (*i == "city_name") { city_name = *j; }
        else if (*i == "owner_domain") { owner_domain = *j; }
        else if (*i == "isp_domain") { isp_domain = *j; }
        else if (*i == "base_station") { base_station = *j; }
    }
}

string ipdb::BaseStationInfo::GetCountryName() { return country_name; }

string ipdb::BaseStationInfo::GetRegionName() { return region_name; }

string ipdb::BaseStationInfo::GetCityName() { return city_name; }

string ipdb::BaseStationInfo::GetOwnerDomain() { return owner_domain; }

string ipdb::BaseStationInfo::GetIspDomain() { return isp_domain; }

string ipdb::BaseStationInfo::GetBaseStation() { return base_station; }

string ipdb::BaseStationInfo::str() {
    stringstream sb;
    sb << "country_name: " << country_name << endl;
    sb << "region_name: " << region_name << endl;
    sb << "city_name: " << city_name << endl;
    sb << "owner_domain: " << owner_domain << endl;
    sb << "isp_domain: " << isp_domain << endl;
    sb << "base_station: " << base_station << endl;
    return sb.str();
}

ipdb::BaseStation::BaseStation(const string &file) : Reader(file) {}

ipdb::BaseStationInfo ipdb::BaseStation::FindInfo(const string &addr, const string &language) {
    return BaseStationInfo(Find(addr, language), this->Fields());
}

ipdb::DistrictInfo::DistrictInfo(const vector<string> &data, const vector<string> &fields) {
    auto i = fields.begin();
    auto j = data.begin();
    for (; i != fields.end() && j != data.end(); ++i, ++j) {
        if (*i == "country_name") { country_name = *j; }
        else if (*i == "region_name") { region_name = *j; }
        else if (*i == "city_name") { city_name = *j; }
        else if (*i == "district_name") { district_name = *j; }
        else if (*i == "china_admin_code") { china_admin_code = *j; }
        else if (*i == "covering_radius") { covering_radius = *j; }
        else if (*i == "latitude") { latitude = *j; }
        else if (*i == "longitude") { longitude = *j; }
    }
}

string ipdb::DistrictInfo::GetCountryName() { return country_name; }

string ipdb::DistrictInfo::GetRegionName() { return region_name; }

string ipdb::DistrictInfo::GetCityName() { return city_name; }

string ipdb::DistrictInfo::GetDistrictName() { return district_name; }

string ipdb::DistrictInfo::GetChinaAdminCode() { return china_admin_code; }

string ipdb::DistrictInfo::GetCoveringRadius() { return covering_radius; }

string ipdb::DistrictInfo::GetLatitude() { return latitude; }

string ipdb::DistrictInfo::GetLongitude() { return longitude; }

string ipdb::DistrictInfo::str() {
    stringstream sb;
    sb << "country_name: " << country_name << endl;
    sb << "region_name: " << region_name << endl;
    sb << "city_name: " << city_name << endl;
    sb << "district_name: " << district_name << endl;
    sb << "china_admin_code: " << china_admin_code << endl;
    sb << "covering_radius: " << covering_radius << endl;
    sb << "latitude: " << latitude << endl;
    sb << "longitude: " << longitude << endl;
    return sb.str();
}

ipdb::District::District(const string &file) : Reader(file) {}

ipdb::DistrictInfo ipdb::District::FindInfo(const string &addr, const string &language) {
    return DistrictInfo(Find(addr, language), this->Fields());
}

ipdb::IDCInfo::IDCInfo(const vector<string> &data, const vector<string> &fields) {
    auto i = fields.begin();
    auto j = data.begin();
    for (; i != fields.end() && j != data.end(); ++i, ++j) {
        if (*i == "country_name") { country_name = *j; }
        else if (*i == "region_name") { region_name = *j; }
        else if (*i == "city_name") { city_name = *j; }
        else if (*i == "owner_domain") { owner_domain = *j; }
        else if (*i == "isp_domain") { isp_domain = *j; }
        else if (*i == "idc") { idc = *j; }
    }
}

string ipdb::IDCInfo::GetCountryName() { return country_name; }

string ipdb::IDCInfo::GetRegionName() { return region_name; }

string ipdb::IDCInfo::GetCityName() { return city_name; }

string ipdb::IDCInfo::GetOwnerDomain() { return owner_domain; }

string ipdb::IDCInfo::GetIspDomain() { return isp_domain; }

string ipdb::IDCInfo::GetIDC() { return idc; }

string ipdb::IDCInfo::str() {
    stringstream sb;
    sb << "country_name: " << country_name << endl;
    sb << "region_name: " << region_name << endl;
    sb << "city_name: " << city_name << endl;
    sb << "owner_domain: " << owner_domain << endl;
    sb << "isp_domain: " << isp_domain << endl;
    sb << "idc: " << idc << endl;
    return sb.str();
}

ipdb::IDC::IDC(const string &file) : Reader(file) {}

ipdb::IDCInfo ipdb::IDC::FindInfo(const string &addr, const string &language) {
    return IDCInfo(Find(addr, language), this->Fields());
}


text:
const babel = require('babel-core');
const content = `
export type Foo = {
  a_string: string,
};

console.log('test');
`;

it('export-object', () => {
  const res = babel.transform(content, {
    babelrc: false,
    presets: ['@babel/env', '@babel/react', '@babel/flow'],
    plugins: [
      '@babel/syntax-flow',
      require('../'),
      "@babel/plugin-proposal-class-properties"
    ],
  }).code;
  expect(res).toMatchSnapshot();
});


text:
window.onload = function() {
    document.getElementById("element").innerHTML = "content injected by test-js.js window.onload JavaScript function: Your skill is great!" ;
}


text:
"""
Cloud Custodian Lambda Provisioning Support

docs/lambda.rst
"""
from __future__ import absolute_import, division, print_function, unicode_literals

import abc
import base64
import imp
import hashlib
import io
import json
import logging
import os
import sys
import time
import tempfile
import zipfile

from boto3.s3.transfer import S3Transfer, TransferConfig
from botocore.exceptions import ClientError

from concurrent.futures import ThreadPoolExecutor

# Static event mapping to help simplify cwe rules creation
from c7n.cwe import CloudWatchEvents
from c7n.logs_support import _timestamp_from_string
from c7n.utils import parse_s3, local_session

log = logging.getLogger('custodian.lambda')
RUNTIME = 'python{}.{}'.format(
    sys.version_info.major,
    sys.version_info.minor,
)

class PythonPackageArchive(object):
    """Creates a zip file for python lambda functions.

    :param tuple modules: the Python modules to add to the archive

    Amazon doesn't give us straightforward docs here, only `an example
    <http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example-deployment-pkg.html#with-s3-example-deployment-pkg-python>`_,
    from which we can infer that they simply unzip the file into a directory on
    ``sys.path``. So what we do is locate all of the ``modules`` specified, and
    add all of the ``.py`` files we find for these modules to a zip file.

    In addition to the modules specified during instantiation, you can add
    arbitrary additional files to the archive using :py:func:`add_file` and
    :py:func:`add_contents`. For example, since we only add ``*.py`` files for
    you, you'll need to manually add files for any compiled extension modules
    that your Lambda requires.

    """

    def __init__(self, *modules):
        self._temp_archive_file = tempfile.NamedTemporaryFile()
        self._zip_file = zipfile.ZipFile(
            self._temp_archive_file, mode='w',
            compression=zipfile.ZIP_DEFLATED)
        self._closed = False
        self.add_modules(*modules)

    @property
    def path(self):
        return self._temp_archive_file.name

    @property
    def size(self):
        if not self._closed:
            raise ValueError("Archive not closed, size not accurate")
        return os.stat(self._temp_archive_file.name).st_size

    def add_modules(self, *modules):
        """Add the named Python modules to the archive. For consistency's sake
        we only add ``*.py`` files, not ``*.pyc``. We also don't add other
        files, including compiled modules. You'll have to add such files
        manually using :py:meth:`add_file`.
        """
        for module in modules:
            path = imp.find_module(module)[1]
            if os.path.isfile(path):
                if not path.endswith('.py'):
                    raise ValueError('We need a *.py source file instead of ' + path)
                self.add_file(path)
            elif os.path.isdir(path):
                for root, dirs, files in os.walk(path):
                    arc_prefix = os.path.relpath(root, os.path.dirname(path))
                    for f in files:
                        if not f.endswith('.py'):
                            continue
                        f_path = os.path.join(root, f)
                        dest_path = os.path.join(arc_prefix, f)
                        self.add_file(f_path, dest_path)

    def add_file(self, src, dest=None):
        """Add the file at ``src`` to the archive.

        If ``dest`` is ``None`` then it is added under just the original
        filename. So ``add_file('foo/bar.txt')`` ends up at ``bar.txt`` in the
        archive, while ``add_file('bar.txt', 'foo/bar.txt')`` ends up at
        ``foo/bar.txt``.

        """
        dest = dest or os.path.basename(src)
        with open(src, 'rb') as fp:
            contents = fp.read()
        self.add_contents(dest, contents)

    def add_py_file(self, src, dest=None):
        """This is a special case of :py:meth:`add_file` that helps for adding
        a ``py`` when a ``pyc`` may be present as well. So for example, if
        ``__file__`` is ``foo.pyc`` and you do:

        .. code-block:: python

          archive.add_py_file(__file__)

        then this method will add ``foo.py`` instead if it exists, and raise
        ``IOError`` if it doesn't.

        """
        src = src[:-1] if src.endswith('.pyc') else src
        self.add_file(src, dest)

    def add_contents(self, dest, contents):
        """Add file contents to the archive under ``dest``.

        If ``dest`` is a path, it will be added compressed and world-readable
        (user-writeable). You may also pass a :py:class:`~zipfile.ZipInfo` for
        custom behavior.

        """
        assert not self._closed, "Archive closed"
        if not isinstance(dest, zipfile.ZipInfo):
            dest = zinfo(dest)  # see for some caveats
        self._zip_file.writestr(dest, contents)

    def close(self):
        """Close the zip file.

        Note underlying tempfile is removed when archive is garbage collected.
        """
        self._closed = True
        self._zip_file.close()
        log.debug(
            "Created custodian lambda archive size: %0.2fmb",
            (os.path.getsize(self._temp_archive_file.name) / (
                1024.0 * 1024.0)))
        return self

    def remove(self):
        """Dispose of the temp file for garbage collection."""
        if self._temp_archive_file:
            self._temp_archive_file = None

    def get_checksum(self):
        """Return the b64 encoded sha256 checksum of the archive."""
        assert self._closed, "Archive not closed"
        with open(self._temp_archive_file.name) as fh:
            return base64.b64encode(checksum(fh, hashlib.sha256()))

    def get_bytes(self):
        """Return the entire zip file as a byte string. """
        assert self._closed, "Archive not closed"
        return open(self._temp_archive_file.name, 'rb').read()

    def get_reader(self):
        """Return a read-only :py:class:`~zipfile.ZipFile`."""
        assert self._closed, "Archive not closed"
        buf = io.BytesIO(self.get_bytes())
        return zipfile.ZipFile(buf, mode='r')

    def get_filenames(self):
        """Return a list of filenames in the archive."""
        return [n.filename for n in self.get_reader().filelist]

def checksum(fh, hasher, blocksize=65536):
    buf = fh.read(blocksize)
    while len(buf) > 0:
        hasher.update(buf)
        buf = fh.read(blocksize)
    return hasher.digest()

def custodian_archive():
    """Create a lambda code archive for running custodian."""
    return PythonPackageArchive('c7n', 'pkg_resources', 'ipaddress')

class LambdaManager(object):
    """ Provides CRUD operations around lambda functions
    """

    def __init__(self, session_factory, s3_asset_path=None):
        self.session_factory = session_factory
        self.client = self.session_factory().client('lambda')
        self.s3_asset_path = s3_asset_path

    def list_functions(self, prefix=None):
        p = self.client.get_paginator('list_functions')
        for rp in p.paginate():
            for f in rp.get('Functions', []):
                if not prefix:
                    yield f
                elif f['FunctionName'].startswith(prefix):
                    yield f

    def publish(self, func, alias=None, role=None, s3_uri=None):
        result, changed = self._create_or_update(
            func, role, s3_uri, qualifier=alias)
        func.arn = result['FunctionArn']
        if alias and changed:
            func.alias = self.publish_alias(result, alias)
        elif alias:
            func.alias = "%s:%s" % (func.arn, alias)
        else:
            func.alias = func.arn

        for e in func.get_events(self.session_factory):
            if e.add(func):
                log.debug(
                    "Added event source: %s to function: %s",
                    e, func.alias)
        return result

    def remove(self, func, alias=None):
        log.info("Removing lambda function %s", func.name)
        for e in func.get_events(self.session_factory):
            e.remove(func)
        try:
            self.client.delete_function(FunctionName=func.name)
        except ClientError as e:
            if e.response['Error']['Code'] != 'ResourceNotFoundException':
                raise

    def metrics(self, funcs, start, end, period=5 * 60):

        def func_metrics(f):
            metrics = local_session(self.session_factory).client('cloudwatch')
            values = {}
            for m in ('Errors', 'Invocations', 'Durations', 'Throttles'):
                values[m] = metrics.get_metric_statistics(
                    Namespace="AWS/Lambda",
                    Dimensions=[{
                        'Name': 'FunctionName',
                        'Value': (
                            isinstance(f, dict) and f['FunctionName'] or f.name)}],
                    Statistics=["Sum"],
                    StartTime=start,
                    EndTime=end,
                    Period=period,
                    MetricName=m)['Datapoints']
            return values

        with ThreadPoolExecutor(max_workers=3) as w:
            results = list(w.map(func_metrics, funcs))
            for m, f in zip(results, funcs):
                if isinstance(f, dict):
                    f['Metrics'] = m
        return results

    def logs(self, func, start, end):
        logs = self.session_factory().client('logs')
        group_name = "/aws/lambda/%s" % func.name
        log.info("Fetching logs from group: %s" % group_name)
        try:
            logs.describe_log_groups(
                logGroupNamePrefix=group_name)
        except ClientError as e:
            if e.response['Error']['Code'] == 'ResourceNotFoundException':
                return
            raise
        try:
            log_streams = logs.describe_log_streams(
                logGroupName=group_name,
                orderBy="LastEventTime", limit=3, descending=True)
        except ClientError as e:
            if e.response['Error']['Code'] == 'ResourceNotFoundException':
                return
            raise
        start = _timestamp_from_string(start)
        end = _timestamp_from_string(end)
        for s in reversed(log_streams['logStreams']):
            result = logs.get_log_events(
                logGroupName=group_name,
                logStreamName=s['logStreamName'],
                startTime=start,
                endTime=end,
            )
            for e in result['events']:
                yield e

    @staticmethod
    def delta_function(old_config, new_config):
        for k in new_config:
            if k not in old_config or new_config[k] != old_config[k]:
                return True

    @staticmethod
    def diff_tags(old_tags, new_tags):
        add = {}
        remove = set()
        for k,v in new_tags.items():
            if k not in old_tags or old_tags[k] != v:
                add[k] = v
        for k in old_tags:
            if k not in new_tags:
                remove.add(k)
        return add, list(remove)

    def _create_or_update(self, func, role=None, s3_uri=None, qualifier=None):
        role = func.role or role
        assert role, "Lambda function role must be specified"
        archive = func.get_archive()
        existing = self.get(func.name, qualifier)

        if s3_uri:
            # TODO: support versioned buckets
            bucket, key = self._upload_func(s3_uri, func, archive)
            code_ref = {'S3Bucket': bucket, 'S3Key': key}
        else:
            code_ref = {'ZipFile': archive.get_bytes()}

        changed = False
        if existing:
            old_config = existing['Configuration']
            if archive.get_checksum() != old_config['CodeSha256']:
                log.debug("Updating function %s code", func.name)
                params = dict(FunctionName=func.name, Publish=True)
                params.update(code_ref)
                result = self.client.update_function_code(**params)
                changed = True
            # TODO/Consider also set publish above to false, and publish
            # after configuration change?

            new_config = func.get_config()
            new_config['Role'] = role
            del new_config['Runtime']
            new_tags = new_config.pop('Tags', {})

            if self.delta_function(old_config, new_config):
                log.debug("Updating function: %s config" % func.name)
                result = self.client.update_function_configuration(**new_config)
                changed = True

            # tag dance
            base_arn = old_config['FunctionArn']
            if base_arn.count(':') > 6:  # trim version/alias
                base_arn = base_arn.rsplit(':', 1)[0]

            old_tags = self.client.list_tags(Resource=base_arn)['Tags']
            tags_to_add, tags_to_remove = self.diff_tags(old_tags, new_tags)

            if tags_to_add:
                log.debug("Adding/updating tags: %s config" % func.name)
                self.client.tag_resource(
                    Resource=base_arn, Tags=tags_to_add)
            if tags_to_remove:
                log.debug("Removing tags: %s config" % func.name)
                self.client.untag_resource(
                    Resource=base_arn, TagKeys=tags_to_remove)

            if not changed:
                result = old_config
        else:
            log.info('Publishing custodian policy lambda function %s', func.name)
            params = func.get_config()
            params.update({'Publish': True, 'Code': code_ref, 'Role': role})
            result = self.client.create_function(**params)
            changed = True

        return result, changed

    def _upload_func(self, s3_uri, func, archive):
        _, bucket, key_prefix = parse_s3(s3_uri)
        key = "%s/%s" % (key_prefix, func.name)
        transfer = S3Transfer(
            self.session_factory().client('s3'),
            config=TransferConfig(
                multipart_threshold=1024 * 1024 * 4))
        transfer.upload_file(
            archive.path,
            bucket=bucket,
            key=key,
            extra_args={
                'ServerSideEncryption': 'AES256'})
        return bucket, key

    def publish_alias(self, func_data, alias):
        """Create or update an alias for the given function.
        """
        if not alias:
            return func_data['FunctionArn']
        func_name = func_data['FunctionName']
        func_version = func_data['Version']

        exists = resource_exists(
            self.client.get_alias, FunctionName=func_name, Name=alias)

        if not exists:
            log.debug("Publishing custodian lambda alias %s", alias)
            alias_result = self.client.create_alias(
                FunctionName=func_name,
                Name=alias,
                FunctionVersion=func_version)
        else:
            if (exists['FunctionVersion'] == func_version and
                    exists['Name'] == alias):
                return exists['AliasArn']
            log.debug('Updating custodian lambda alias %s', alias)
            alias_result = self.client.update_alias(
                FunctionName=func_name,
                Name=alias,
                FunctionVersion=func_version)
        return alias_result['AliasArn']

    def get(self, func_name, qualifier=None):
        params = {'FunctionName': func_name}
        if qualifier:
            params['Qualifier'] = qualifier
        return resource_exists(
            self.client.get_function, **params)

def resource_exists(op, NotFound="ResourceNotFoundException", *args, **kw):
    try:
        return op(*args, **kw)
    except ClientError as e:
        if e.response['Error']['Code'] == NotFound:
            return False
        raise

class AbstractLambdaFunction:
    """Abstract base class for lambda functions."""
    __metaclass__ = abc.ABCMeta

    alias = None

    @abc.abstractproperty
    def name(self):
        """Name for the lambda function"""

    @abc.abstractproperty
    def runtime(self):
        """ """

    @abc.abstractproperty
    def description(self):
        """ """

    @abc.abstractproperty
    def handler(self):
        """ """

    @abc.abstractproperty
    def memory_size(self):
        """ """

    @abc.abstractproperty
    def timeout(self):
        """ """

    @abc.abstractproperty
    def role(self):
        """ """

    @abc.abstractproperty
    def subnets(self):
        """ """

    @abc.abstractproperty
    def security_groups(self):
        """ """

    @abc.abstractproperty
    def dead_letter_config(self):
        """ """

    @abc.abstractproperty
    def environment(self):
        """ """

    @abc.abstractproperty
    def kms_key_arn(self):
        """ """

    @abc.abstractproperty
    def tracing_config(self):
        """ """

    @abc.abstractproperty
    def tags(self):
        """ """

    @abc.abstractmethod
    def get_events(self, session_factory):
        """event sources that should be bound to this lambda."""

    @abc.abstractmethod
    def get_archive(self):
        """Return the lambda distribution archive object."""

    def get_config(self):
        conf = {
            'FunctionName': self.name,
            'MemorySize': self.memory_size,
            'Role': self.role,
            'Description': self.description,
            'Runtime': self.runtime,
            'Handler': self.handler,
            'Timeout': self.timeout,
            'DeadLetterConfig': self.dead_letter_config,
            'Environment': self.environment,
            'KMSKeyArn': self.kms_key_arn,
            'TracingConfig': self.tracing_config,
            'Tags': self.tags}
        if self.subnets and self.security_groups:
            conf['VpcConfig'] = {
                'SubnetIds': self.subnets,
                'SecurityGroupIds': self.security_groups}
        return conf

class LambdaFunction(AbstractLambdaFunction):

    def __init__(self, func_data, archive):
        self.func_data = func_data
        required = set((
            'name', 'handler', 'memory_size',
            'timeout', 'role', 'runtime',
            'description'))
        missing = required.difference(func_data)
        if missing:
            raise ValueError("Missing required keys %s" % " ".join(missing))
        self.archive = archive

    @property
    def name(self):
        return self.func_data['name']

    @property
    def description(self):
        return self.func_data['description']

    @property
    def handler(self):
        return self.func_data['handler']

    @property
    def memory_size(self):
        return self.func_data['memory_size']

    @property
    def timeout(self):
        return self.func_data['timeout']

    @property
    def runtime(self):
        return self.func_data['runtime']

    @property
    def role(self):
        return self.func_data['role']

    @property
    def security_groups(self):
        return self.func_data.get('security_groups', None)

    @property
    def subnets(self):
        return self.func_data.get('subnets', None)

    @property
    def dead_letter_config(self):
        return self.func_data.get('dead_letter_config', {})

    @property
    def environment(self):
        return self.func_data.get('environment', {})

    @property
    def kms_key_arn(self):
        return self.func_data.get('kms_key_arn', '')

    @property
    def tracing_config(self):
        return self.func_data.get('tracing_config', {})

    @property
    def tags(self):
        return self.func_data.get('tags', {})

    def get_events(self, session_factory):
        return self.func_data.get('events', ())

    def get_archive(self):
        return self.archive

PolicyHandlerTemplate = """\
from c7n import handler

def run(event, context):
    return handler.dispatch_event(event, context)

"""

class PolicyLambda(AbstractLambdaFunction):
    """Wraps a custodian policy to turn it into lambda function.
    """
    handler = "custodian_policy.run"
    runtime = "python2.7"

    def __init__(self, policy):
        self.policy = policy
        self.archive = custodian_archive()

    @property
    def name(self):
        return "custodian-%s" % self.policy.name

    @property
    def description(self):
        return self.policy.data.get(
            'description', 'cloud-custodian lambda policy')

    @property
    def role(self):
        return self.policy.data['mode'].get('role', '')

    @property
    def memory_size(self):
        return self.policy.data['mode'].get('memory', 512)

    @property
    def timeout(self):
        return self.policy.data['mode'].get('timeout', 60)

    @property
    def security_groups(self):
        return None

    @property
    def subnets(self):
        return None

    @property
    def dead_letter_config(self):
        return self.policy.data['mode'].get('dead_letter_config', {})

    @property
    def environment(self):
        return self.policy.data['mode'].get('environment', {})

    @property
    def kms_key_arn(self):
        return self.policy.data['mode'].get('kms_key_arn', '')

    @property
    def tracing_config(self):
        return self.policy.data['mode'].get('tracing_config', {})

    @property
    def tags(self):
        return self.policy.data['mode'].get('tags', {})

    def get_events(self, session_factory):
        events = []
        if self.policy.data['mode']['type'] == 'config-rule':
            events.append(
                ConfigRule(self.policy.data['mode'], session_factory))
        else:
            events.append(
                CloudWatchEventSource(
                    self.policy.data['mode'], session_factory))
        return events

    def get_archive(self):
        self.archive.add_contents(
            'config.json', json.dumps(
                {'policies': [self.policy.data]}, indent=2))
        self.archive.add_contents('custodian_policy.py', PolicyHandlerTemplate)
        self.archive.close()
        return self.archive

def zinfo(fname):
    """Amazon lambda exec environment setup can break itself
    if zip files aren't constructed a particular way.

    ie. It respects file perm attributes from the zip including
    those that prevent lambda from working. Namely lambda
    extracts code as one user, and executes code as a different
    user. Without permissions for the executing user to read
    the file the lambda function is broken.

    Python's default zipfile.writestr does a 0600 perm which
    we modify here as a workaround.
    """
    info = zipfile.ZipInfo(fname)
    # Grant other users permissions to read
    # http://unix.stackexchange.com/questions/14705/
    info.external_attr = 0o644 << 16
    return info

class CloudWatchEventSource(object):
    """Subscribe a lambda to cloud watch events.

    Cloud watch events supports a number of different event
    sources, from periodic timers with cron syntax, to
    real time instance state notifications, cloud trail
    events, and realtime asg membership changes.

    Event Pattern for Instance State

    .. code-block:: json

       {
         "source": ["aws.ec2"],
         "detail-type": ["EC2 Instance State-change Notification"],
         "detail": { "state": ["pending"]}
       }

    Event Pattern for Cloud Trail API

    .. code-block:: json

       {
         "detail-type": ["AWS API Call via CloudTrail"],
         "detail": {
            "eventSource": ["s3.amazonaws.com"],
            "eventName": ["CreateBucket", "DeleteBucket"]
         }
       }
    """
    ASG_EVENT_MAPPING = {
        'launch-success': 'EC2 Instance Launch Successful',
        'launch-failure': 'EC2 Instance Launch Unsuccessful',
        'terminate-success': 'EC2 Instance Terminate Successful',
        'terminate-failure': 'EC2 Instance Terminate Unsuccessful'}

    def __init__(self, data, session_factory, prefix="custodian-"):
        self.session_factory = session_factory
        self.session = session_factory()
        self.client = self.session.client('events')
        self.data = data
        self.prefix = prefix

    def _make_notification_id(self, function_name):
        if not function_name.startswith(self.prefix):
            return "%s%s" % (self.prefix, function_name)
        return function_name

    def get(self, rule_name):
        return resource_exists(
            self.client.describe_rule,
            Name=self._make_notification_id(rule_name))

    @staticmethod
    def delta(src, tgt):
        """Given two cwe rules determine if the configuration is the same.

        Name is already implied.
        """
        for k in ['State', 'EventPattern', 'ScheduleExpression']:
            if src.get(k) != tgt.get(k):
                return True
        return False

    def __repr__(self):
        return "<CWEvent Type:%s Events:%s>" % (
            self.data.get('type'),
            ', '.join(map(str, self.data.get('events', []))))

    def resolve_cloudtrail_payload(self, payload):
        sources = self.data.get('sources', [])
        events = []
        for e in self.data.get('events'):
            if not isinstance(e, dict):
                events.append(e)
                event_info = CloudWatchEvents.get(e)
                if event_info is None:
                    continue
            else:
                event_info = e
                events.append(e['event'])
            sources.append(event_info['source'])

        payload['detail'] = {
            'eventSource': list(set(sources)),
            'eventName': events}

    def render_event_pattern(self):
        event_type = self.data.get('type')
        payload = {}
        if event_type == 'cloudtrail':
            payload['detail-type'] = ['AWS API Call via CloudTrail']
            self.resolve_cloudtrail_payload(payload)

        elif event_type == "ec2-instance-state":
            payload['source'] = ['aws.ec2']
            payload['detail-type'] = [
                "EC2 Instance State-change Notification"]
            # Technically could let empty be all events, but likely misconfig
            payload['detail'] = {"state": self.data.get('events', [])}
        elif event_type == "asg-instance-state":
            payload['source'] = ['aws.autoscaling']
            events = []
            for e in self.data.get('events', []):
                events.append(self.ASG_EVENT_MAPPING.get(e, e))
            payload['detail-type'] = events
        elif event_type == 'periodic':
            pass
        else:
            raise ValueError(
                "Unknown lambda event source type: %s" % event_type)
        if not payload:
            return None
        return json.dumps(payload)

    def add(self, func):
        params = dict(
            Name=func.name, Description=func.description, State='ENABLED')

        pattern = self.render_event_pattern()
        if pattern:
            params['EventPattern'] = pattern
        schedule = self.data.get('schedule')
        if schedule:
            params['ScheduleExpression'] = schedule

        rule = self.get(func.name)

        if rule and self.delta(rule, params):
            log.debug("Updating cwe rule for %s" % self)
            response = self.client.put_rule(**params)
        elif not rule:
            log.debug("Creating cwe rule for %s" % (self))
            response = self.client.put_rule(**params)
        else:
            response = {'RuleArn': rule['Arn']}

        try:
            self.session.client('lambda').add_permission(
                FunctionName=func.name,
                StatementId=func.name,
                SourceArn=response['RuleArn'],
                Action='lambda:InvokeFunction',
                Principal='events.amazonaws.com')
            log.debug('Added lambda invoke cwe rule permission')
        except ClientError as e:
            if e.response['Error']['Code'] != 'ResourceConflictException':
                raise

        # Add Targets
        found = False
        response = self.client.list_targets_by_rule(Rule=func.name)
        # CWE seems to be quite picky about function arns (no aliases/versions)
        func_arn = func.arn

        if func_arn.count(':') > 6:
            func_arn, version = func_arn.rsplit(':', 1)
        for t in response['Targets']:
            if func_arn == t['Arn']:
                found = True

        if found:
            return

        log.debug('Creating cwe rule target for %s on func:%s' % (
            self, func_arn))

        self.client.put_targets(
            Rule=func.name, Targets=[{"Id": func.name, "Arn": func_arn}])

        return True

    def update(self, func):
        self.add(func)

    def pause(self, func):
        try:
            self.client.disable_rule(Name=func.name)
        except:
            pass

    def resume(self, func):
        try:
            self.client.enable_rule(Name=func.name)
        except:
            pass

    def remove(self, func):
        if self.get(func.name):
            try:
                targets = self.client.list_targets_by_rule(
                    Rule=func.name)['Targets']
                self.client.remove_targets(
                    Rule=func.name,
                    Ids=[t['Id'] for t in targets])
            except ClientError as e:
                log.warning(
                    "Could not remove targets for rule %s error: %s",
                    func.name, e)
            self.client.delete_rule(Name=func.name)

class BucketLambdaNotification(object):
    """ Subscribe a lambda to bucket notifications directly. """

    def __init__(self, data, session_factory, bucket):
        self.data = data
        self.session_factory = session_factory
        self.session = session_factory()
        self.bucket = bucket

    def delta(self, src, tgt):
        for k in ['Id', 'LambdaFunctionArn', 'Events', 'Filters']:
            if src.get(k) != tgt.get(k):
                return True
        return False

    def _get_notifies(self, s3, func):
        notifies = s3.get_bucket_notification_configuration(
            Bucket=self.bucket['Name'])
        found = False
        for f in notifies.get('LambdaFunctionConfigurations', []):
            if f['Id'] != func.name:
                continue
            found = f
        return notifies, found

    def add(self, func):
        s3 = self.session.client('s3')
        notifies, found = self._get_notifies(s3, func)
        notifies.pop('ResponseMetadata', None)
        func_arn = func.arn
        if func_arn.rsplit(':', 1)[-1].isdigit():
            func_arn = func_arn.rsplit(':', 1)[0]
        n_params = {
            'Id': func.name,
            'LambdaFunctionArn': func_arn,
            'Events': self.data.get('events', ['s3:ObjectCreated:*'])}
        if self.data.get('filters'):
            n_params['Filters'] = {
                'Key': {'FilterRules': self.filters}}

        if found:
            if self.delta(found, n_params):
                notifies['LambdaFunctionConfigurations'].remove(found)
            else:
                log.info("Bucket lambda notification present")
                return

        lambda_client = self.session.client('lambda')
        params = dict(
            FunctionName=func.name,
            StatementId=self.bucket['Name'],
            Action='lambda:InvokeFunction',
            Principal='s3.amazonaws.com')
        if self.data.get('account_s3'):
            params['SourceAccount'] = self.data['account_s3']
            params['SourceArn'] = 'arn:aws:s3:::*'
        else:
            params['SourceArn'] = 'arn:aws:s3:::%' % self.bucket['Name']
        try:
            lambda_client.add_permission(**params)
        except ClientError as e:
            if e.response['Error']['Code'] != 'ResourceConflictException':
                raise

        notifies.setdefault('LambdaFunctionConfigurations', []).append(n_params)
        s3.put_bucket_notification_configuration(
            Bucket=self.bucket['Name'], NotificationConfiguration=notifies)

        return True

    def remove(self, func):
        s3 = self.session.client('s3')
        notifies, found = self._get_notifies(s3, func)
        if not found:
            return

        lambda_client = self.session.client('lambda')
        try:
            response = lambda_client.remove_permission(
                FunctionName=func['FunctionName'],
                StatementId=self.bucket['Name'])
            log.debug("Removed lambda permission result: %s" % response)
        except ClientError as e:
            if e.response['Error']['Code'] != 'ResourceNotFoundException':
                raise

        notifies['LambdaFunctionConfigurations'].remove(found)
        s3.put_bucket_notification_configuration(
            Bucket=self.bucket['Name'],
            NotificationConfiguration=notifies)

class CloudWatchLogSubscription(object):
    """ Subscribe a lambda to a log group[s]
    """

    iam_delay = 1.5

    def __init__(self, session_factory, log_groups, filter_pattern):
        self.log_groups = log_groups
        self.filter_pattern = filter_pattern
        self.session_factory = session_factory
        self.session = session_factory()
        self.client = self.session.client('logs')

    def add(self, func):
        lambda_client = self.session.client('lambda')
        for group in self.log_groups:
            log.info(
                "Creating subscription filter for %s" % group['logGroupName'])
            region = group['arn'].split(':', 4)[3]
            try:
                lambda_client.add_permission(
                    FunctionName=func.name,
                    StatementId=group['logGroupName'][1:].replace('/', '-'),
                    SourceArn=group['arn'],
                    Action='lambda:InvokeFunction',
                    Principal='logs.%s.amazonaws.com' % region)
                log.debug("Added lambda ipo nvoke log group permission")
                # iam eventual consistency and propagation
                time.sleep(self.iam_delay)
            except ClientError as e:
                if e.response['Error']['Code'] != 'ResourceConflictException':
                    raise
            # Consistent put semantics / ie no op if extant
            self.client.put_subscription_filter(
                logGroupName=group['logGroupName'],
                filterName=func.name,
                filterPattern=self.filter_pattern,
                destinationArn=func.alias or func.arn)

    def remove(self, func):
        lambda_client = self.session.client('lambda')
        for group in self.log_groups:
            try:
                response = lambda_client.remove_permission(
                    FunctionName=func.name,
                    StatementId=group['logGroupName'][1:].replace('/', '-'))
                log.debug("Removed lambda permission result: %s" % response)
            except ClientError as e:
                if e.response['Error']['Code'] != 'ResourceNotFoundException':
                    raise

            try:
                response = self.client.delete_subscription_filter(
                    logGroupName=group['logGroupName'], filterName=func.name)
                log.debug("Removed subscription filter from: %s",
                          group['logGroupName'])
            except ClientError as e:
                if e.response['Error']['Code'] != 'ResourceNotFoundException':
                    raise

class SNSSubscription(object):
    """ Subscribe a lambda to one or more SNS topics.
    """

    iam_delay = 1.5

    def __init__(self, session_factory, topic_arns):
        self.topic_arns = topic_arns
        self.session_factory = session_factory
        self.session = session_factory()
        self.client = self.session.client('sns')

    @staticmethod
    def _parse_arn(arn):
        parts = arn.split(':')
        region, topic_name = parts[3], parts[5]
        statement_id = 'sns-topic-' + topic_name
        return region, topic_name, statement_id

    def add(self, func):
        lambda_client = self.session.client('lambda')
        for arn in self.topic_arns:
            region, topic_name, statement_id = self._parse_arn(arn)

            log.info("Subscribing %s to %s" % (func.name, topic_name))

            # Add permission to lambda for sns invocation.
            try:
                lambda_client.add_permission(
                    FunctionName=func.name,
                    StatementId='sns-topic-' + topic_name,
                    SourceArn=arn,
                    Action='lambda:InvokeFunction',
                    Principal='sns.amazonaws.com')
                log.debug("Added permission for sns to invoke lambda")
                # iam eventual consistency and propagation
                time.sleep(self.iam_delay)
            except ClientError as e:
                if e.response['Error']['Code'] != 'ResourceConflictException':
                    raise

            # Subscribe the lambda to the topic.
            topic = self.session.resource('sns').Topic(arn)
            topic.subscribe(Protocol='lambda', Endpoint=func.arn)  # idempotent

    def remove(self, func):
        lambda_client = self.session.client('lambda')
        for topic_arn in self.topic_arns:
            region, topic_name, statement_id = self._parse_arn(topic_arn)

            try:
                response = lambda_client.remove_permission(
                    FunctionName=func.name,
                    StatementId=statement_id)
                log.debug("Removed lambda permission result: %s" % response)
            except ClientError as e:
                if e.response['Error']['Code'] != 'ResourceNotFoundException':
                    raise

            paginator = self.client.get_paginator('list_subscriptions_by_topic')

            class Done(Exception):
                pass
            try:
                for page in paginator.paginate(TopicArn=topic_arn):
                    for subscription in page['Subscriptions']:
                        if subscription['Endpoint'] != func.arn:
                            continue
                        try:
                            response = self.client.unsubscribe(
                                SubscriptionArn=subscription['SubscriptionArn'])
                            log.debug("Unsubscribed %s from %s" %
                                (func.name, topic_name))
                        except ClientError as e:
                            code = e.response['Error']['Code']
                            if code != 'ResourceNotFoundException':
                                raise
                        raise Done  # break out of both for loops
            except Done:
                pass

class BucketSNSNotification(SNSSubscription):
    """ Subscribe a lambda to bucket notifications via SNS. """

    def __init__(self, session_factory, bucket, topic=None):
        # NB: We are overwriting __init__ vs. extending.
        self.session_factory = session_factory
        self.session = session_factory()
        self.topic_arns = self.get_topic(bucket) if topic is None else [topic]
        self.client = self.session.client('sns')

    def get_topic(self, bucket):
        session = local_session(self.session_factory)
        sns = session.client('sns')
        s3 = session.client('s3')

        notifies = bucket['Notification']
        if 'TopicConfigurations' not in notifies:
            notifies['TopicConfigurations'] = []
        all_topics = notifies['TopicConfigurations']
        topic_arns = [t['TopicArn'] for t in all_topics
                      if 's3:ObjectCreated:*' in t['Events']]
        if not topic_arns:
            # No suitable existing topic. Create one.
            topic_arn = sns.create_topic(Name=bucket['Name'])['TopicArn']
            policy = {
                'Statement': [{
                    'Action': 'SNS:Publish',
                    'Effect': 'Allow',
                    'Resource': topic_arn,
                    'Principal': {'Service': 's3.amazonaws.com'}}]}
            sns.set_topic_attributes(
                TopicArn=topic_arn,
                AttributeName='Policy',
                AttributeValue=json.dumps(policy))
            notifies['TopicConfigurations'].append({
                'TopicArn': topic_arn,
                'Events': ['s3:ObjectCreated:*']})
            s3.put_bucket_notification_configuration(Bucket=bucket['Name'],
                NotificationConfiguration=notifies)
            topic_arns = [topic_arn]
        return topic_arns

class ConfigRule(object):
    """Use a lambda as a custom config rule.

    """

    def __init__(self, data, session_factory):
        self.data = data
        self.session_factory = session_factory
        self.session = session_factory()
        self.client = self.session.client('config')

    def __repr__(self):
        return "<ConfigRule>"

    def get_rule_params(self, func):
        # config does not support versions/aliases on lambda funcs
        func_arn = func.arn
        if func_arn.count(':') > 6:
            func_arn, version = func_arn.rsplit(':', 1)

        params = dict(
            ConfigRuleName=func.name,
            Description=func.description,
            Source={
                'Owner': 'CUSTOM_LAMBDA',
                'SourceIdentifier': func_arn,
                'SourceDetails': [{
                    'EventSource': 'aws.config',
                    'MessageType': 'ConfigurationItemChangeNotification'}]
            }
        )

        if isinstance(func, PolicyLambda):
            manager = func.policy.get_resource_manager()
            config_type = manager.get_model().config_type
            params['Scope'] = {
                'ComplianceResourceTypes': [config_type]}
        else:
            params['Scope']['ComplianceResourceTypes'] = self.data.get(
                'resource-types', ())
        return params

    def get(self, rule_name):
        rules = resource_exists(
            self.client.describe_config_rules,
            ConfigRuleNames=[rule_name],
            NotFound="NoSuchConfigRuleException")
        if not rules:
            return rules
        return rules['ConfigRules'][0]

    @staticmethod
    def delta(rule, params):
        # doesn't seem like we have anything mutable at the moment,
        # since we restrict params, maybe reusing the same policy name
        # with a different resource type.
        if rule['Scope'] != params['Scope']:
            return True
        if rule['Source'] != params['Source']:
            return True
        if rule.get('Description', '') != rule.get('Description', ''):
            return True
        return False

    def add(self, func):
        rule = self.get(func.name)
        params = self.get_rule_params(func)

        if rule and self.delta(rule, params):
            log.debug("Updating config rule for %s" % self)
            rule.update(params)
            return self.client.put_config_rule(ConfigRule=rule)
        elif rule:
            log.debug("Config rule up to date")
            return
        try:
            self.session.client('lambda').add_permission(
                FunctionName=func.name,
                StatementId=func.name,
                SourceAccount=func.arn.split(':')[4],
                Action='lambda:InvokeFunction',
                Principal='config.amazonaws.com')
        except ClientError as e:
            if e.response['Error']['Code'] != 'ResourceConflictException':
                raise

        log.debug("Adding config rule for %s" % func.name)
        return self.client.put_config_rule(ConfigRule=params)

    def remove(self, func):
        rule = self.get(func.name)
        if not rule:
            return
        try:
            self.client.delete_config_rule(
                ConfigRuleName=func.name)
        except ClientError as e:
            if e.response['Error']['Code'] != 'ResourceNotFoundException':
                raise


text:
namespace kasko {

bool ReadCrashKeysFromFile(
    const base::FilePath& file_path,
    std::map<base::string16, base::string16>* crash_keys) {
  DCHECK(crash_keys);
  std::string file_contents;
  if (!base::ReadFileToString(file_path, &file_contents)) {
    LOG(ERROR) << "Failed to read crash keys from file " << file_path.value();
    return false;
  }

  scoped_ptr<base::Value> value(base::JSONReader::Read(file_contents));
  base::DictionaryValue* dictionary = nullptr;
  if (!value || !value->GetAsDictionary(&dictionary)) {
    LOG(ERROR) << "The crash keys file contents from " << file_path.value()
               << " are not a valid JSON dictionary:\n" << file_contents;
    return false;
  }

  for (base::DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd();
       it.Advance()) {
    base::string16 value;
    if (!it.value().GetAsString(&value)) {
      LOG(ERROR) << "The crash keys file contents from " << file_path.value()
                 << " contain an invalid value for entry " << it.key()
                 << ". File Contents:\n" << file_contents;
      return false;
    }
    crash_keys->insert(std::make_pair(base::UTF8ToWide(it.key()), value));
  }
  return true;
}

bool WriteCrashKeysToFile(
    const base::FilePath& file_path,
    const std::map<base::string16, base::string16>& crash_keys) {
  base::DictionaryValue dictionary;
  for (const auto& entry : crash_keys) {
    dictionary.SetStringWithoutPathExpansion(base::WideToUTF8(entry.first),
                                             base::WideToUTF8(entry.second));
  }

  std::string file_contents;
  if (!base::JSONWriter::Write(&dictionary, &file_contents)) {
    LOG(ERROR) << "Failed to serialize crash keys.";
    return false;
  }

  if (!base::WriteFile(file_path, file_contents.data(),
                       file_contents.length())) {
    LOG(ERROR) << "Failed to write serialized crash keys to "
               << file_path.value();
    return false;
  }

  return true;
}

}  // namespace kasko


text:
package com.vitco.app.layout.content.layer;

import javax.swing.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *  Text-field that only allows hex numbers and has an easy way to retrieve the current color
 *  also allows for notification listen (and change "onChange")
 */
public class SaveTextArea extends JTextArea {

    // filter to allow only certain chars in textarea and notify on change
    // also remembers the current string
    private static class AxisJTextFilter extends DocumentFilter {
        @Override
        public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException
        {
            StringBuilder sb = new StringBuilder();
            sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
            sb.insert(offset, text);
            if(invalidContent(sb.toString())) return;
            fb.insertString(offset, text, attr);
        }

        @Override
        public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr) throws BadLocationException
        {
            StringBuilder sb = new StringBuilder();
            sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
            sb.replace(offset, offset + length, text);
            if(invalidContent(sb.toString())) return;
            fb.replace(offset, length, text, attr);
        }

        @Override
        public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException
        {
            super.remove(fb, offset, length);
        }

        private final Pattern pattern = Pattern.compile("^[A-Za-z0-9 \\Q!~@#$%^&*()-_=+[]{}\\|;:'\",.<>/?\\E]{0,30}$");

        public boolean invalidContent(String text)
        {
            Matcher matcher = pattern.matcher(text);
            boolean isMatch = matcher.matches();
            return !isMatch;
        }
    }

    public SaveTextArea(String value) {
        super(value);
        ((AbstractDocument)this.getDocument()).setDocumentFilter(new AxisJTextFilter());
    }
}


text:
package com.rrafols.packt.chart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import java.text.DecimalFormat;

public class Chart extends View {
    private float[] dataPoints;
    private Paint linePaint;
    private Paint circlePaint;
    private Paint backgroundPaint;
    private Path graphPath;
    private Path circlePath;
    private Path backgroundPath;
    private boolean regenerate;
    private float lastWidth;
    private float lastHeight;
    private Rect textBoundaries;
    private float minValue;
    private float verticalDelta;
    private DecimalFormat decimalFormat;
    private String[] labels;
    private String[] verticalLabels;
    private boolean invertVerticalAxis;
    private boolean drawLegend;

    public Chart(Context context, AttributeSet attrs) {
        super(context, attrs);

        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setColor(0xffffffff);
        linePaint.setStrokeWidth(8.f);
        linePaint.setStyle(Paint.Style.STROKE);

        circlePaint = new Paint();
        circlePaint.setAntiAlias(true);
        circlePaint.setColor(0xffff2020);
        circlePaint.setStyle(Paint.Style.FILL);

        backgroundPaint = new Paint();
        backgroundPaint.setColor(0xffFFFF80);
        backgroundPaint.setStyle(Paint.Style.STROKE);
        backgroundPaint.setPathEffect(new DashPathEffect(new float[] {5, 5}, 0));
        backgroundPaint.setTextSize(20.f);

        graphPath = new Path();
        circlePath = new Path();
        backgroundPath = new Path();
        lastWidth = -1;
        lastHeight = -1;

        textBoundaries = new Rect();
        decimalFormat = new DecimalFormat("#.##");
        verticalLabels = new String[11];

        invertVerticalAxis = false;
        drawLegend = true;
    }

    // make a copy of the data as the original array content might change.
    public void setDataPoints(float[] originalData) {
        dataPoints = new float[originalData.length];

        float maxValue = Float.MIN_VALUE;
        minValue = Float.MAX_VALUE;
        for (int i = 0; i < dataPoints.length; i++) {
            dataPoints[i] = originalData[i];
            if (dataPoints[i] < minValue) minValue = dataPoints[i];
            if (dataPoints[i] > maxValue) maxValue = dataPoints[i];
        }

        verticalDelta = maxValue - minValue;

        for (int i = 0; i < dataPoints.length; i++) {
            dataPoints[i] = (dataPoints[i] - minValue) / verticalDelta;
        }

        regenerate = true;
        postInvalidate();
    }

    public void setInvertVerticalAxis(boolean invertVerticalAxis) {
        this.invertVerticalAxis = invertVerticalAxis;
        regenerate = true;
        postInvalidate();
    }

    public void setDrawLegend(boolean drawLegend) {
        this.drawLegend = drawLegend;
        regenerate = true;
        postInvalidate();
    }

    public void setLabels(String[] labels) {
        this.labels = labels;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawARGB(255,0 ,0 ,0);

        float maxLabelWidth = 0.f;
        if (drawLegend && regenerate) {
            for (int i = 0; i <= 10; i++) {
                float step;

                if (!invertVerticalAxis) {
                    step = ((float) i / 10.f);
                } else {
                    step = ((float) (10 - i)) / 10.f;
                }

                float value = step * verticalDelta + minValue;
                verticalLabels[i] = decimalFormat.format(value);
                backgroundPaint.getTextBounds(verticalLabels[i], 0, verticalLabels[i].length(), textBoundaries);
                if (textBoundaries.width() > maxLabelWidth) {
                    maxLabelWidth = textBoundaries.width();
                }
            }
        }

        float labelLeftPadding = getPaddingLeft() + maxLabelWidth * 0.25f;
        float leftPadding = getPaddingLeft() + maxLabelWidth * 1.5f;
        float rightPadding = getPaddingRight();
        float topPadding = getPaddingTop();

        float width = canvas.getWidth() - leftPadding - rightPadding;
        float height = canvas.getHeight() - topPadding - getPaddingBottom()
                - backgroundPaint.getTextSize() + 0.5f;

        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
            leftPadding = getPaddingEnd();
            labelLeftPadding = leftPadding + width + maxLabelWidth * 0.25f;
        }

        if (lastWidth != width || lastHeight != height) {
            regenerate = true;

            lastWidth = width;
            lastHeight = height;
        }

        if (regenerate) {
            circlePath.reset();
            graphPath.reset();
            backgroundPath.reset();

            if (labels == null) {
                labels = new String[dataPoints.length + 1];
                for (int i = 0; i < labels.length; i++) {
                    labels[i] = "" + i;
                }
            }

            for (int i = 0; i <= dataPoints.length; i++) {
                float xl = width * (((float) i) / dataPoints.length) + leftPadding;
                backgroundPath.moveTo(xl, topPadding);
                backgroundPath.lineTo(xl, topPadding + height);
            }

            for (int i = 0; i <= 10; i++) {
                float yl = ((float) i / 10.f) * height + topPadding;
                backgroundPath.moveTo(leftPadding, yl);
                backgroundPath.lineTo(leftPadding + width, yl);
            }

            float x = leftPadding;
            float y = height * getDataPoint(0) + topPadding;

            graphPath.moveTo(x, y);
            circlePath.addCircle(x, y, 10, Path.Direction.CW);

            for (int i = 1; i < dataPoints.length; i++) {
                x = width * (((float) i + 1) / dataPoints.length) + leftPadding;
                y = height * getDataPoint(i) + topPadding;

                graphPath.lineTo(x, y);
                circlePath.addCircle(x, y, 10, Path.Direction.CW);
            }

            regenerate = false;
        }

        if (drawLegend) {
            canvas.drawPath(backgroundPath, backgroundPaint);

            // draw bottom legend
            for (int i = 0; i <= dataPoints.length; i++) {
                float xl = width * (((float) i) / dataPoints.length) + leftPadding;
                backgroundPaint.getTextBounds(labels[i], 0, labels[i].length(), textBoundaries);
                canvas.drawText(labels[i],
                        xl - (textBoundaries.width() / 2),
                        height + topPadding + backgroundPaint.getTextSize() * 1.5f,
                        backgroundPaint);
            }

            // draw side legend
            for (int i = 0; i <= 10; i++) {
                float step = ((float) i / 10.f);
                float yl = step * height + topPadding
                        + backgroundPaint.getTextSize() * 0.5f;

                canvas.drawText(verticalLabels[i],
                        labelLeftPadding,
                        yl,
                        backgroundPaint);
            }
        }

        canvas.drawPath(graphPath, linePaint);
        canvas.drawPath(circlePath, circlePaint);
    }

    private float getDataPoint(int i) {
        float data = dataPoints[i];
        return invertVerticalAxis ? 1.f - data : data;
    }
}