text:
"""
    Admin Controllers
"""

import cPickle as pickle
import csv
from gluon.admin import *
from gluon.fileutils import listdir

module = "admin"

# Options Menu (available in all Functions' Views)
# - can Insert/Delete items from default menus within a function, if required.
response.menu_options = admin_menu_options

# S3 framework functions
# -----------------------------------------------------------------------------
def index():

    """ Module's Home Page """

    module_name = deployment_settings.modules[module].name_nice
    response.title = module_name
    return dict(module_name=module_name)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def setting():

    """ RESTful CRUD controller """

    resourcename = request.function
    tablename = "s3_" + resourcename
    table = db[tablename]

    table.admin_name.label = T("Admin Name")
    table.admin_email.label = T("Admin Email")
    table.admin_tel.label = T("Admin Tel")
    #table.utc_offset.label = T("UTC Offset")
    table.theme.label = T("Theme")
    table.theme.comment = DIV(A(T("Add Theme"), _class="colorbox", _href=URL(r=request, c="admin", f="theme", args="create", vars=dict(format="popup")), _target="top", _title=T("Add Theme"))),
    #table.archive_not_delete.label = T("Archive not Delete")
    #table.archive_not_delete.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Archive not Delete") + "|" + T("If this setting is enabled then all deleted records are just flagged as deleted instead of being really deleted. They will appear in the raw database access but won't be visible to normal users."))
    #table.debug.label = T("Debug")
    #table.debug.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Debug") + "|" + T("Switch this on to use individual CSS/Javascript files for diagnostics during development."))
    #table.self_registration.label = T("Self Registration")
    #table.self_registration.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Self-registration") + "|" + T("Can users register themselves for authenticated login access?"))
    #table.security_policy.label = T("Security Policy")
    #table.security_policy.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Security Policy") + "|" + T("The simple policy allows anonymous users to Read & registered users to Edit. The full security policy allows the administrator to set permissions on individual tables or records - see models/zzz.py."))
    #table.audit_read.label = T("Audit Read")
    #table.audit_read.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Audit Read") + "|" + T("If enabled then a log is maintained of all records a user accesses. If disabled then it can still be enabled on a per-module basis."))
    #table.audit_write.label = T("Audit Write")
    #table.audit_write.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Audit Write") + "|" + T("If enabled then a log is maintained of all records a user edits. If disabled then it can still be enabled on a per-module basis."))

    s3.crud_strings[tablename] = Storage(
        title_update = T("Edit Settings"),
        msg_record_modified = T("Settings updated"),
        label_list_button = None)

    s3xrc.model.configure(table,
                          deletable=False,
                          listadd=False,
                          #onvalidation=theme_check,
                          #update_next = URL(r=request, args=[1, "update"])
                          onaccept=theme_apply)

    output = s3_rest_controller("s3", resourcename, list_btn=None)
    return output

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def theme():
    """ RESTful CRUD controller """
    resource = "theme"
    tablename = module + "_" + resource
    table = db[tablename]

    # Model options
    table.name.label = T("Name")
    #table.logo.label = T("Logo")
    #table.logo.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Logo") + "|" + T("Name of the file (& optional sub-path) located in static which should be used for the top-left image."))
    #table.header_background.label = T("Header Background")
    #table.header_background.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Header Background") + "|" + T("Name of the file (& optional sub-path) located in static which should be used for the background of the header."))
    #table.footer.label = T("Footer")
    #table.footer.comment = A(SPAN("[Help]"), _class="tooltip", _title=T("Footer") + "|" + T("Name of the file (& optional sub-path) located in views which should be used for footer."))
    table.col_background.label = T("Background Colour")
    table.col_txt.label = T("Text Colour for Text blocks")
    table.col_txt_background.label = T("Background Colour for Text blocks")
    table.col_txt_border.label = T("Border Colour for Text blocks")
    table.col_txt_underline.label = T("Colour for Underline of Subheadings")
    table.col_menu.label = T("Colour of dropdown menus")
    table.col_highlight.label = T("Colour of selected menu items")
    table.col_input.label = T("Colour of selected Input fields")
    table.col_border_btn_out.label = T("Colour of bottom of Buttons when not pressed")
    table.col_border_btn_in.label = T("Colour of bottom of Buttons when pressed")
    table.col_btn_hover.label = T("Colour of Buttons when hovering")

    # CRUD Strings
    ADD_THEME = T("Add Theme")
    LIST_THEMES = T("List Themes")
    s3.crud_strings[resource] = Storage(
        title_create = ADD_THEME,
        title_display = T("Theme Details"),
        title_list = LIST_THEMES,
        title_update = T("Edit Theme"),
        title_search = T("Search Themes"),
        subtitle_create = T("Add New Theme"),
        subtitle_list = T("Themes"),
        label_list_button = LIST_THEMES,
        label_create_button = ADD_THEME,
        msg_record_created = T("Theme added"),
        msg_record_modified = T("Theme updated"),
        msg_record_deleted = T("Theme deleted"),
        msg_list_empty = T("No Themes currently defined"))

    s3xrc.model.configure(table,
                          #onvalidation=theme_check,
                          #list_fields=["id", "name", "logo", "footer", "col_background"],
                          list_fields=["id", "name", "col_background"],
                          )

    return s3_rest_controller(module, resource)
    s3xrc.model.clear_config(table, "onvalidation")

# -----------------------------------------------------------------------------
def theme_apply(form):
    "Apply the Theme specified by Form"
    if form.vars.theme:
        # Valid form
        # Relevant paths
        template = os.path.join(request.folder, "static", "styles", "S3", "template.css")
        tmp_folder = os.path.join(request.folder, "static", "scripts", "tools")
        out_file = os.path.join(request.folder, "static", "styles", "S3", "sahana.css")
        out_file2 = os.path.join(request.folder, "static", "styles", "S3", "sahana.min.css")
        # Check permissions
        if not os.access(template, os.R_OK):
            session.error = T("Template file %s not readable - unable to apply theme!" % template)
            redirect(URL(r=request, args=request.args))
        if not os.access(tmp_folder, os.W_OK):
            session.error = T("Temp folder %s not writable - unable to apply theme!" % tmp_folder)
            redirect(URL(r=request, args=request.args))
        if not os.access(out_file, os.W_OK):
            session.error = T("CSS file %s not writable - unable to apply theme!" % out_file)
            redirect(URL(r=request, args=request.args))
        if not os.access(out_file2, os.W_OK):
            session.error = T("CSS file %s not writable - unable to apply theme!" % out_file2)
            redirect(URL(r=request, args=request.args))
        # Read in Template
        inpfile = open(template, "r")
        lines = inpfile.readlines()
        inpfile.close()
        # Read settings from Database
        theme = db(db.admin_theme.id == form.vars.theme).select(limitby=(0, 1)).first()
        default_theme = db(db.admin_theme.id == 1).select(limitby=(0, 1)).first()
        #if theme.logo:
        #    logo = theme.logo
        #else:
        #    logo = default_theme.logo
        #if theme.header_background:
        #    header_background = theme.header_background
        #else:
        #    header_background = default_theme.header_background
        # Write out CSS
        ofile = open(out_file, "w")
        for line in lines:
            #line = line.replace("YOURLOGOHERE", logo)
            #line = line.replace("HEADERBACKGROUND", header_background )
            # Iterate through Colours
            for key in theme.keys():
                if key[:4] == "col_":
                    if theme[key]:
                        line = line.replace(key, theme[key])
                    else:
                        line = line.replace(key, default_theme[key])
            ofile.write(line)
        ofile.close()

        # Minify
        from subprocess import PIPE, check_call
        currentdir = os.getcwd()
        os.chdir(os.path.join(currentdir, request.folder, "static", "scripts", "tools"))
        import sys
        # If started as a Windows service, os.sys.executable is no longer python
        if ("win" in sys.platform):
            pythonpath = os.path.join(sys.prefix, "python.exe")
        else:
            pythonpath = os.sys.executable
        try:
            proc = check_call([pythonpath, "build.sahana.py", "CSS", "NOGIS"], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
        except:
            session.error = T("Error encountered while applying the theme.")
            redirect(URL(r=request, args=request.args))
        os.chdir(currentdir)

        # Don't do standard redirect to List view as we only want this option available
        redirect(URL(r=request, args=[1, "update"]))
    else:
        session.error = INVALIDREQUEST
        redirect(URL(r=request))

# -----------------------------------------------------------------------------
def theme_check(form):
    "Check the Theme has valid files available. Deprecated"
    # Check which form we're called by
    if form.vars.theme:
        # Called from Settings
        theme = db(db.admin_theme.id == form.vars.theme).select(db.admin_theme.logo, limitby=(0, 1)).first()
        logo = theme.logo
        #header_background = theme.header_background
        #footer = theme.footer
    #elif form.vars.logo and form.vars.footer:
    elif form.vars.logo:
        # Called from Theme
        logo = form.vars.logo
        #header_background = form.vars.header_background
        #footer = form.vars.footer
    else:
        session.error = INVALIDREQUEST
        redirect(URL(r=request))

    _logo = os.path.join(request.folder, "static", logo)
    #_header_background = os.path.join(request.folder, "static", header_background)
    #_footer = os.path.join(request.folder, "views", footer)
    if not os.access(_logo, os.R_OK):
        form.errors["logo"] = T("Logo file %s missing!" % logo)
        return
    #if not os.access(_header_background, os.R_OK):
    #    form.errors["header_background"] = T("Header background file %s missing!" % logo)
    #    return
    #if not os.access(_footer, os.R_OK):
    #    form.errors["footer"] = T("Footer file %s missing!" % footer)
    #    return
    # Validation passed
    return

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def user():
    """ RESTful CRUD controller """
    module = "auth"
    resource = "user"
    tablename = module + "_" + resource
    table = db[tablename]

    # Model options
    role_manager = s3base.S3RoleManager()
    s3xrc.model.set_method(module, resource, method="roles", action=role_manager)

    # CRUD Strings
    ADD_USER = T("Add User")
    LIST_USERS = T("List Users")
    s3.crud_strings[tablename] = Storage(
        title_create = ADD_USER,
        title_display = T("User Details"),
        title_list = LIST_USERS,
        title_update = T("Edit User"),
        title_search = T("Search Users"),
        subtitle_create = T("Add New User"),
        subtitle_list = T("Users"),
        label_list_button = LIST_USERS,
        label_create_button = ADD_USER,
        label_delete_button = T("Delete User"),
        msg_record_created = T("User added"),
        msg_record_modified = T("User updated"),
        msg_record_deleted = T("User deleted"),
        msg_list_empty = T("No Users currently registered"))

    # Allow the ability for admin to Disable logins
    db.auth_user.registration_key.writable = True
    db.auth_user.registration_key.readable = True
    db.auth_user.registration_key.label = T("Disabled?")

    # In Controller to allow registration to work with UUIDs - only manual edits need this setting
    db.auth_user.registration_key.requires = IS_NULL_OR(IS_IN_SET(["disabled", "pending"]))

    # Pre-processor
    def user_prep(jr):
        if jr.method == "delete" and jr.http=="GET":
            if jr.id == jr.session.auth.user.id: # we're trying to delete ourself
                request.get_vars.update({"user.id":str(jr.id)})
                jr.id = None
                s3xrc.model.configure(table,
                                      delete_next = URL(r=request, c="default", f="user/logout"))
                s3.crud.confirm_delete = T("You are attempting to delete your own account - are you sure you want to proceed?")

        elif jr.method == "update":
            # Send an email to user if their account is approved
            # (=moved from 'pending' to 'blank'(i.e. enabled))
            s3xrc.model.configure(table,
                                  onvalidation = lambda form: user_approve(form))
        if jr.http == "GET" and not jr.method:
            session.s3.cancel = jr.here()
        return True
    response.s3.prep = user_prep

    s3xrc.model.configure(table,
        main="first_name",
        # Add users to Person Registry & 'Authenticated' role:
        create_onaccept = lambda form: auth.s3_register(form),
        create_onvalidation = lambda form: user_create_onvalidation(form))
    output = s3_rest_controller(module, resource)

    if response.s3.actions:
        response.s3.actions.insert(1,
                    dict(label=str(T("Roles")), _class="action-btn",
                         url=str(URL(r=request, c="admin", f="user", args=["[id]", "roles"]))))
    return output

# -----------------------------------------------------------------------------
def user_create_onvalidation (form):
    if (form.request_vars.has_key("password_two") and \
        form.request_vars.password != form.request_vars.password_two):
        form.errors.password = T("Password fields don't match")
    return True

# -----------------------------------------------------------------------------
def user_approve(form):
    "Send an email to user if their account is approved (moved from 'pending' to 'blank'(i.e. enabled))"
    if form.vars.registration_key:
        # Now non-blank
        return
    else:
        # Now blank - lookup old value
        status = db(db.auth_user.id == request.vars.id).select(db.auth_user.registration_key, limitby=(0, 1)).first().registration_key
        if status == "pending":
            # Send email to user confirming that they are now able to login
            if not auth.settings.mailer or \
                   not auth.settings.mailer.send(to=form.vars.email,
                        subject=s3.messages.confirmation_email_subject,
                        message=s3.messages.confirmation_email):
                    session.warning = auth.messages.unable_send_email
                    return
        else:
            return

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def usergroup():
    """
        User update form with groups
        - NB This is currently unused & has no custom view
    """
    user = request.vars.user

    # redirect to the user list if user id is not given
    if user is None:
        redirect(URL(r=request, f="user"))
        return

    # gather common variables
    data = {}
    data["user_id"] = user
    data["username"] = db.auth_user[user].first_name + " " + \
                       db.auth_user[user].last_name
    data["role"] = db.auth_group[user].role

    # display the standard user details
    record = db(db.auth_user.id == user).select().first()
    db.auth_user.id.readable = False

    # Let admin view and modify the registration key
    db.auth_user.registration_key.writable = True
    db.auth_user.registration_key.readable = True
    db.auth_user.registration_key.label = T("Disabled?")
    db.auth_user.registration_key.requires = IS_NULL_OR(IS_IN_SET(["disabled", "pending"]))

    form = SQLFORM(db.auth_user, record, deletable=True)

    # find all groups user belongs to
    query = (db.auth_membership.user_id == user)
    allgroups = db().select(db.auth_group.ALL)
    user_membership = db(query).select(db.auth_membership.ALL)

    # db.auth_group[row.group_id].role
    #records = SQLTABLE(db(query).select(db.auth_membership.ALL))

    # handle the M to M of user to group membership for display
    records = []
    for group in allgroups:

        user_group_count = 0

        for row in user_membership:

            if (row.group_id == group.id):
                records.append([group.role, "on", group.id])
                user_group_count += 1

        if (user_group_count == 0):
            # if the group does not exist currently and is enabled
            #if request.has_key(group.id):
            if (group.id == 6):
                db.auth_membership.insert(user_id = user, group_id = group.id)
                records.append([group.role, "on", group.id])
                data["heehe"] = "yes %d" % group.id

            records.append([group.role, "", group.id])

    # Update records for user details
    if form.accepts(request.vars): \
                    response.flash="User " + data["username"] + " Updated"
    elif form.errors: \
                    response.flash="There were errors in the form"

    # Update records for group membership details
    for key in request.vars.keys():
        data["m_" + key] = request.vars[key]

    return dict(data=data, records=records, form=form)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def group():

    """ RESTful CRUD controller """

    prefix = "auth"
    resourcename = "group"
    tablename = "%s_%s" % (prefix, resourcename)
    table = db[tablename]

    # Model options

    # CRUD Strings
    ADD_ROLE = T("Add Role")
    LIST_ROLES = T("List Roles")
    s3.crud_strings[tablename] = Storage(
        title_create = ADD_ROLE,
        title_display = T("Role Details"),
        title_list = LIST_ROLES,
        title_update = T("Edit Role"),
        title_search = T("Search Roles"),
        subtitle_create = T("Add New Role"),
        subtitle_list = T("Roles"),
        label_list_button = LIST_ROLES,
        label_create_button = ADD_ROLE,
        msg_record_created = T("Role added"),
        msg_record_modified = T("Role updated"),
        msg_record_deleted = T("Role deleted"),
        msg_list_empty = T("No Roles currently defined"))

    s3xrc.model.configure(table, main="role")
    return s3_rest_controller(prefix, resourcename)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def membership():

    """ RESTful CRUD controller """

    prefix = "auth"
    resourcename = "membership"
    tablename = prefix + "_" + resourcename
    table = db[tablename]

    # Model options
    db.auth_membership.group_id.represent = shn_role_represent
    db.auth_membership.user_id.represent = shn_user_represent

    # CRUD Strings
    ADD_MEMBERSHIP = T("Add Membership")
    LIST_MEMBERSHIPS = T("List Memberships")
    s3.crud_strings[tablename] = Storage(
        title_create = ADD_MEMBERSHIP,
        title_display = T("Membership Details"),
        title_list = LIST_MEMBERSHIPS,
        title_update = T("Edit Membership"),
        title_search = T("Search Memberships"),
        subtitle_create = T("Add New Membership"),
        subtitle_list = T("Memberships"),
        label_list_button = LIST_MEMBERSHIPS,
        label_create_button = ADD_MEMBERSHIP,
        msg_record_created = T("Membership added"),
        msg_record_modified = T("Membership updated"),
        msg_record_deleted = T("Membership deleted"),
        msg_list_empty = T("No Memberships currently defined"))

    s3xrc.model.configure(table, main="user_id")
    return s3_rest_controller(prefix, resourcename)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def users():
    """
    List/amend which users are in a Group

    @deprecated

    """

    try:
        group = int(request.args(0))
    except TypeError, ValueError:
        session.error = T("Need to specify a role!")
        redirect(URL(r=request, f="group"))

    table = db.auth_membership
    query = table.group_id == group
    title = T("Role") + ": " + db.auth_group[group].role
    description = db.auth_group[group].description
    # Start building the Return
    output = dict(title=title, description=description, group=group)

    if auth.settings.username:
        username = "username"
    else:
        username = "email"

    # Audit
    crud.settings.create_onaccept = lambda form: s3_audit("create", module, "membership",
                                                          form=form,
                                                          representation="html")
    crud.settings.create_onvalidation = lambda form: group_dupes(form, "users", [group])
    # Many<>Many selection (Deletable, no Quantity)
    item_list = []
    sqlrows = db(query).select()
    even = True
    for row in sqlrows:
        if even:
            theclass = "even"
            even = False
        else:
            theclass = "odd"
            even = True
        id = row.user_id
        _user = db.auth_user[id]
        item_first = _user.first_name
        item_second = _user.last_name
        item_description = _user[username]
        id_link = A(id, _href=URL(r=request, f="user", args=[id, "read"]))
        checkbox = INPUT(_type="checkbox", _value="on", _name=id, _class="remove_item")
        item_list.append(TR(TD(id_link), TD(item_first), TD(item_second), TD(item_description), TD(checkbox), _class=theclass))

    if auth.settings.username:
        username_label = T("Username")
    else:
        username_label = T("Email")
    table_header = THEAD(TR(TH("ID"), TH(T("First Name")), TH(T("Last Name")), TH(username_label), TH(T("Remove"))))
    table_footer = TFOOT(TR(TD(_colspan=4), TD(INPUT(_id="submit_delete_button", _type="submit", _value=T("Remove")))))
    items = DIV(FORM(
        TABLE(table_header,
              TBODY(item_list),
              table_footer, _id="list", _class="display"), _name="custom", _method="post", _enctype="multipart/form-data", _action=URL(r=request, f="group_remove_users", args=[group])))

    subtitle = T("Users")
    crud.messages.submit_button = T("Add")
    crud.messages.record_created = T("Role Updated")
    form = crud.create(table, next=URL(r=request, args=[group]))
    addtitle = T("Add New User to Role")
    output.update(dict(subtitle=subtitle, items=items, addtitle=addtitle, form=form))
    return output

# -----------------------------------------------------------------------------
def group_dupes(form, page, arg):
    """
    Onvalidation check for duplicate user roles

    @deprecated

    """

    user = form.latest["user_id"]
    group = form.latest["group_id"]
    query = (form.table.user_id == user) & (form.table.group_id == group)
    items = db(query).select()
    if items:
        session.error = T("User already has this role")
        redirect(URL(r=request, f=page, args=arg))

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def group_remove_users():
    """
        Remove users from a group
    """
    if len(request.args) == 0:
        session.error = T("Need to specify a group!")
        redirect(URL(r=request, f="group"))
    group = request.args(0)
    table = db.auth_membership
    for var in request.vars:
        if str(var).isdigit():
            user = var
            query = (table.group_id == group) & (table.user_id == user)
            db(query).delete()
    # Audit
    #crud.settings.update_onaccept = lambda form: shn_audit_update(form, "membership", "html")
    session.flash = T("Users removed")
    redirect(URL(r=request, f="users", args=[group]))

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def groups():
    """
        List/amend which groups a User is in
    """

    try:
        user = int(request.args(0))
    except TypeError, ValueError:
        session.error = T("Need to specify a user!")
        redirect(URL(r=request, f="user"))

    table = db.auth_membership
    query = table.user_id == user
    title = db.auth_user[user].first_name + " " + db.auth_user[user].last_name
    description = db.auth_user[user].email
    # Start building the Return
    output = dict(title=title, description=description, user=user)

    # Audit
    crud.settings.create_onaccept = lambda form: s3_audit("create", module, "membership",
                                                          form=form,
                                                          representation="html")

    crud.settings.create_onvalidation = lambda form: group_dupes(form, "groups", [user])
    # Many<>Many selection (Deletable, no Quantity)
    item_list = []
    sqlrows = db(query).select()
    even = True
    for row in sqlrows:
        if even:
            theclass = "even"
            even = False
        else:
            theclass = "odd"
            even = True
        id = row.group_id
        _group = db.auth_group[id]
        item_first = _group.role
        item_description = _group.description
        id_link = A(id, _href=URL(r=request, f="group", args=[id, "read"]))
        checkbox = INPUT(_type="checkbox", _value="on", _name=id, _class="remove_item")
        item_list.append(TR(TD(id_link), TD(item_first), TD(item_description), TD(checkbox), _class=theclass))

    table_header = THEAD(TR(TH("ID"), TH(T("Role")), TH(T("Description")), TH(T("Remove"))))
    table_footer = TFOOT(TR(TD(_colspan=3), TD(INPUT(_id="submit_delete_button", _type="submit", _value=T("Remove")))))
    items = DIV(FORM(TABLE(table_header, TBODY(item_list), table_footer, _id="table-container"), _name="custom", _method="post", _enctype="multipart/form-data", _action=URL(r=request, f="user_remove_groups", args=[user])))

    subtitle = T("Roles")
    crud.messages.submit_button = T("Add")
    crud.messages.record_created = T("User Updated")
    form = crud.create(table, next=URL(r=request, args=[user]))
    addtitle = T("Add New Role to User")
    output.update(dict(subtitle=subtitle, items=items, addtitle=addtitle, form=form))
    return output

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def user_remove_groups():
    """ Remove groups from a user """
    if len(request.args) == 0:
        session.error = T("Need to specify a user!")
        redirect(URL(r=request, f="user"))
    user = request.args(0)
    table = db.auth_membership
    for var in request.vars:
        if str(var).isdigit():
            group = var
            query = (table.group_id == group) & (table.user_id == user)
            db(query).delete()
    # Audit
    #crud.settings.update_onaccept = lambda form: shn_audit_update(form, "membership", "html")
    session.flash = T("Groups removed")
    redirect(URL(r=request, f="groups", args=[user]))

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def import_data():
    """
        Import data via POST upload to CRUD controller. Old - being replaced by Sync/Importer.
    """
    title = T("Import Data")
    crud.messages.submit_button = "Upload"

    # Deprecated
    import_job_form = crud.create(db.admin_import_job)
    # Tell the CRUD create form to post to a different location
    import_job_form.custom.begin.text = str(import_job_form.custom.begin).replace(
            'action=""',
            'action="%s"' % URL(r=request, f="import_job", args=["create"]))

    return dict(title=title,
                import_job_form=import_job_form)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def import_csv_data():
    """
        Import CSV data via POST upload to Database.
    """
    file = request.vars.multifile.file
    try:
        # Assumes that it is a concatenation of tables
        import_csv(file)
        session.flash = T("Data uploaded")
    except Exception, e:
        session.error = T("Unable to parse CSV file!")
    redirect(URL(r=request, f="import_data"))

# -----------------------------------------------------------------------------
@auth.requires_login()
def export_data():
    """
        Export data via CRUD controller. Old - being replaced by Sync.
    """
    title = T("Export Data")
    return dict(title=title)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def export_csv():
    """
        Export entire database as CSV. Old - being replaced by Sync.
    """
    import StringIO
    output = StringIO.StringIO()

    db.export_to_csv_file(output)

    output.seek(0)
    import gluon.contenttype
    response.headers["Content-Type"] = gluon.contenttype.contenttype(".csv")
    filename = "%s_database.csv" % (request.env.server_name)
    response.headers["Content-disposition"] = "attachment; filename=%s" % filename
    return output.read()

# -----------------------------------------------------------------------------
# Unstructured Data Import
# Deprecated - being replaced by Importer
@auth.s3_requires_membership(1)
def import_job():
    "RESTful CRUD controller to handle 'jobs' for importing unstructured data."
    # CRUD Strings
    module = "admin"
    resource = "import_job"
    table = "%s_%s" % (module, resource)
    # This breaks!
    jr = s3xrc.request(module, resource, request, session=session)
    CREATE_NEW_IMPORT_JOB = T("Create New Import Job")
    LIST_IMPORT_JOBS = ("List Import Jobs")
    s3.crud_strings[table] = Storage(
            title_create=CREATE_NEW_IMPORT_JOB,
            title_display=T("Import Job"),
            title_list=LIST_IMPORT_JOBS,
            title_update=T("Update Import Job"),
            subtitle_create=CREATE_NEW_IMPORT_JOB,
            subtitle_list=T("Import Jobs"),
            label_list_button=LIST_IMPORT_JOBS,
            label_create_button=T("Create Import Job"),
            msg_record_created=T("Import job created"),
            msg_list_empty=T("No import jobs")
    )

    if len(request.args) == 0:
        return _import_job_list(jr)
    action = request.args(0)
    if action == "create":
        return _import_job_create(jr)
    if action == "update":
        return _import_job_update(jr)

# -----------------------------------------------------------------------------
def _import_job_list(jr):
    return shn_list(jr, listadd=False)

# -----------------------------------------------------------------------------
def _import_job_create(jr):
    if jr.http != "POST":
        redirect(jr.there())

    def process_new_file_and_redirect(form):
        filename = form.vars.source_file_newfilename
        filepath = os.path.join(request.folder, "uploads", filename)
        query = (jr.table.id == form.vars.id)
        column_map = []
        model_fields = dict(map(
                lambda x:(x.lower(), x),
                get_matchable_fields(form.vars.module, form.vars.resource)))
        try:
            reader = csv.reader(open(filepath, "r"))
            for line in reader:
                for col in line:
                    field = None
                    col_match = col.lower()
                    if col_match in model_fields:
                        # Explicit name match.
                        field = model_fields.pop(col_match)
                    if not field:
                        # Partial name patch.
                        for field_name in model_fields:
                            if col_match in field_name or field_name in col_match:
                                field = model_fields.pop(field_name)
                                break
                    column_map.append((col, field))
                break
            pickled_map = pickle.dumps(column_map, pickle.HIGHEST_PROTOCOL)
            db(query).update(column_map=pickled_map)
        except:
            db(query).update(status="failed")
        redirect(URL(r=request, f="import_job", args=[form.vars.id, "update"]))

    form = crud.create(jr.table, onaccept=process_new_file_and_redirect)
    response.flash = "Form errors!"
    redirect(URL(r=request, f="import_data"))

# -----------------------------------------------------------------------------
def _import_job_update(jr):
    if len(request.args) < 2:
        redirect(jr.there())
    id = request.args[1]
    query = (jr.table.id == id)
    job = db(query).select()
    if not job:
        raise HTTP(404, body=s3xrc.xml.json_message(False, 404, session.error))
    job = job[0]

    if jr.http == "GET":
        output = _import_job_update_GET(jr, job)
    elif jr.http == "POST":
        output = _import_job_update_POST(jr, job)
    else:
        raise HTTP(400, body=INVALIDREQUEST)

    title = "%s - %s" % (T("Input Job"), job.description)
    output.update(dict(title=title, job=job))
    response.view = "admin/import_job_update.html"
    return output

# -----------------------------------------------------------------------------
def _import_job_update_GET(jr, job):
    table = db.admin_import_line
    query = (table.import_job == job.id)

    if job.status == "new":
        try:
            job.column_map = pickle.loads(job.column_map)
        except pickle.UnpicklingError:
            job.column_map = []
        model_fields = get_matchable_fields(job.module, job.resource)
        return dict(model_fields=model_fields)

    if job.status == "processing":
        num_lines = db(query).count()
        return dict(num_lines=num_lines, update_speed=60)

    if job.status in ["processed", "failed", "imported"]:
        def _include_field(f):
            if f in ["import_job"]:
                return False
            return table[f].readable

        fields = [table[f] for f in table.fields if _include_field(f)]
        headers = dict(map(lambda f: (str(f), f.label), fields))
        items = crud.select(
                db["admin_import_line"],
                query=query,
                fields=fields,
                headers=headers,
                truncate=48, _id="list", _class="display")
        response.extra_styles = ["admin/import_job.css"]
        return dict(items=items)

    if job.status == "import":
        query = (table.import_job == job.id) & (table.status == "imported")
        num_lines = db(query).count()
        return dict(num_lines=num_lines, update_speed=60)

    return {}

# -----------------------------------------------------------------------------
def _import_job_update_POST(jr, job):
    if job.status == "new":
        # Update column map.
        try:
            column_map = pickle.loads(job.column_map)
        except pickle.UnpicklingError:
            column_map = []
        for key, value in request.vars.iteritems():
            if not key.startswith("column_map_"):
                continue
            try:
                idx = int(key.split("_")[-1])
            except ValueError:
                continue
            if value != "None (Ignore)":
                column_map[idx] = (column_map[idx][0], value)
            else:
                column_map[idx] = (column_map[idx][0], None)
        jr.table[job.id] = dict(
                column_map=pickle.dumps(column_map, pickle.HIGHEST_PROTOCOL),
                status="processing")
        job.status = "processing"

    if job.status == "processed":
        query = db.admin_import_line.id
        for var, status in request.vars.iteritems():
            if not var.startswith("status_"):
                continue
            try:
                import_line_id = int(var.split("_")[-1])
            except ValueError:
                continue
            db(db.admin_import_line.id == import_line_id).update(status=status)
        jr.table[job.id] = dict(status="import")
        job.status = "import"

    return _import_job_update_GET(jr, job)

# -----------------------------------------------------------------------------
def get_matchable_fields(module, resource):
    model_fields = getattr(db, "%s_%s" % (module, resource)).fields
    for name in ["created_on", "modified_on", "id", "uuid", "deleted"]:
        model_fields.remove(name)
    model_fields.insert(0, "None (Ignore)")
    return model_fields

# -----------------------------------------------------------------------------
# Functional Testing
# Deprecated: Use static/selenium/scripts/regressionTests.py with it's Tk UI
def handleResults():
    """
        Process the POST data returned from Selenium TestRunner.
        The data is written out to 2 files.  The overall results are written to
        date-time-browserName-metadata.txt as a list of key: value, one per line.  The
        suiteTable and testTables are written to date-time-browserName-results.html.
    """

    if not request.vars.result:
        # No results
        return

    # Read in results
    result = request.vars.result
    totalTime = request.vars.totalTime
    numberOfSuccesses = request.vars.numTestPasses
    numberOfFailures = request.vars.numTestFailures
    numberOfCommandSuccesses = request.vars.numCommandPasses
    numberOfCommandFailures = request.vars.numCommandFailures
    numberOfCommandErrors = request.vars.numCommandErrors

    suiteTable = ""
    if request.vars.suite:
        suiteTable = request.vars.suite

    testTables = []
    testTableNum = 1
    while request.vars["testTable.%s" % testTableNum]:
        testTable = request.vars["testTable.%s" % testTableNum]
        testTables.append(testTable)
        testTableNum += 1
        try:
            request.vars["testTable.%s" % testTableNum]
            pass
        except:
            break

    # Unescape the HTML tables
    import urllib
    suiteTable = urllib.unquote(suiteTable)
    testTables = map(urllib.unquote, testTables)

    # We want to store results separately for each browser
    browserName = getBrowserName(request.env.http_user_agent)
    date = str(request.utcnow)[:-16]
    time = str(request.utcnow)[11:-10]
    time = time.replace(":", "-")

    # Write out results
    outputDir = os.path.join(request.folder, "static", "selenium", "results")
    metadataFile = "%s-%s-%s-metadata.txt" % (date, time, browserName)
    dataFile = "%s-%s-%s-results.html" % (date, time, browserName)

    #xmlText = '<selenium result="' + result + '" totalTime="' + totalTime + '" successes="' + numberOfCommandSuccesses + '" failures="' + numberOfCommandFailures + '" errors="' + numberOfCommandErrors + '" />'
    f = open(os.path.join(outputDir, metadataFile), "w")
    for key in request.vars.keys():
        if "testTable" in key or key in ["log", "suite"]:
            pass
        else:
            print >> f, "%s: %s" % (key, request.vars[key])
    f.close()

    f = open(os.path.join(outputDir, dataFile), "w")
    print >> f, suiteTable
    for testTable in testTables:
        print >> f, "<br/><br/>"
        print >> f, testTable
    f.close()

    message = DIV(P("Results have been successfully posted to the server here:"),
        P(A(metadataFile, _href=URL(r=request, c="static", f="selenium", args=["results", metadataFile]))),
        P(A(dataFile, _href=URL(r=request, c="static", f="selenium", args=["results", dataFile]))))

    response.view = "display.html"
    title = T("Test Results")
    return dict(title=title, item=message)

# -----------------------------------------------------------------------------
# Ticket Viewer functions Borrowed from admin application of web2py
@auth.s3_requires_membership(1)
def errors():
    """ Error handler """

    app = request.application

    for item in request.vars:
        if item[:7] == "delete_":
            os.unlink(apath("%s/errors/%s" % (app, item[7:]), r=request))

    func = lambda p: os.stat(apath("%s/errors/%s" % (app, p), r=request)).st_mtime
    tickets = sorted(listdir(apath("%s/errors/" % app, r=request), "^\w.*"),
                     key=func,
                     reverse=True)

    return dict(app=app, tickets=tickets)

# -----------------------------------------------------------------------------
def make_link(path):
    """ Create a link from a path """
    tryFile = path.replace("\\", "/")

    if os.path.isabs(tryFile) and os.path.isfile(tryFile):
        (folder, filename) = os.path.split(tryFile)
        (base, ext) = os.path.splitext(filename)
        app = request.args[0]

        editable = {"controllers": ".py", "models": ".py", "views": ".html"}
        for key in editable.keys():
            check_extension = folder.endswith("%s/%s" % (app, key))
            if ext.lower() == editable[key] and check_extension:
                return A('"' + tryFile + '"',
                         _href=URL(r=request,
                         f="edit/%s/%s/%s" % (app, key, filename))).xml()
    return ""

# -----------------------------------------------------------------------------
def make_links(traceback):
    """ Make links using the given traceback """

    lwords = traceback.split('"')

    # Make the short circuit compatible with <= python2.4
    result = (len(lwords) != 0) and lwords[0] or ""

    i = 1

    while i < len(lwords):
        link = make_link(lwords[i])

        if link == "":
            result += '"' + lwords[i]
        else:
            result += link

            if i + 1 < len(lwords):
                result += lwords[i + 1]
                i = i + 1

        i = i + 1

    return result

# -----------------------------------------------------------------------------
class TRACEBACK(object):
    """ Generate the traceback """

    def __init__(self, text):
        """ TRACEBACK constructor """

        self.s = make_links(CODE(text).xml())

    def xml(self):
        """ Returns the xml """

        return self.s

# -----------------------------------------------------------------------------
# Ticket viewing
@auth.s3_requires_membership(1)
def ticket():
    """ Ticket handler """

    if len(request.args) != 2:
        session.flash = T("Invalid ticket")
        redirect(URL(r=request))

    app = request.args[0]
    ticket = request.args[1]
    e = RestrictedError()
    e.load(request, app, ticket)

    return dict(app=app,
                ticket=ticket,
                traceback=TRACEBACK(e.traceback),
                code=e.code,
                layer=e.layer)

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def role():
    """
    Role Manager

    @author: Dominic König <dominic@aidiq.com>

    """

    prefix = "auth"
    name = "group"

    # ACLs as component of roles
    s3xrc.model.add_component("s3", "permission",
        joinby = dict(auth_group="group_id"),
        multiple=True)

    def prep(r):
        if r.representation not in ("html",):
            return False

        handler = s3base.S3RoleManager()
        modules = deployment_settings.modules
        handler.controllers = Storage([(m, modules[m]) for m in modules
                                                       if modules[m].restricted])

        # Configure REST methods
        resource = r.resource
        resource.add_method("users", handler)
        resource.set_handler("read", handler)
        resource.set_handler("list", handler)
        resource.set_handler("copy", handler)
        resource.set_handler("create", handler)
        resource.set_handler("update", handler)
        resource.set_handler("delete", handler)
        return True
    response.s3.prep = prep

    response.s3.no_sspag = True
    response.extra_styles = ["S3/role.css"]

    output = s3_rest_controller(prefix, name)
    return output

# -----------------------------------------------------------------------------
@auth.s3_requires_membership(1)
def acl():
    """
    Preliminary controller for ACLs
    for testing purposes, not for production use!

    """

    prefix = "s3"
    name = "permission"

    table = auth.permission.table
    table.group_id.requires = IS_ONE_OF(db, "auth_group.id", "%(role)s")
    table.group_id.represent = lambda opt: opt and db.auth_group[opt].role or opt

    table.controller.requires = IS_EMPTY_OR(IS_IN_SET(auth.permission.modules.keys(), zero="ANY"))
    table.controller.represent = lambda opt: opt and "%s (%s)" % (opt, auth.permission.modules.get(opt, {}).get("name_nice", opt)) or "ANY"

    table.function.represent = lambda val: val and val or T("ANY")

    table.tablename.requires = IS_EMPTY_OR(IS_IN_SET([t._tablename for t in db], zero=T("ANY")))
    table.tablename.represent = lambda val: val and val or T("ANY")

    table.uacl.label = T("All Resources")
    table.uacl.widget = S3ACLWidget.widget
    table.uacl.requires = IS_ACL(auth.permission.PERMISSION_OPTS)
    table.uacl.represent = lambda val: acl_represent(val, auth.permission.PERMISSION_OPTS)

    table.oacl.label = T("Owned Resources")
    table.oacl.widget = S3ACLWidget.widget
    table.oacl.requires = IS_ACL(auth.permission.PERMISSION_OPTS)
    table.oacl.represent = lambda val: acl_represent(val, auth.permission.PERMISSION_OPTS)

    s3xrc.model.configure(table,
        create_next = URL(r=request),
        update_next = URL(r=request))

    if "_next" in request.vars:
        next = request.vars._next
        s3xrc.model.configure(table, delete_next=next)

    output = s3_rest_controller(prefix, name)
    return output

# -----------------------------------------------------------------------------
def acl_represent(acl, options):
    """
    Represent ACLs in tables
    for testing purposes, not for production use!

    """

    values = []

    for o in options.keys():
        if o == 0 and acl == 0:
            values.append("%s" % options[o][0])
        elif acl and acl & o == o:
            values.append("%s" % options[o][0])
        else:
            values.append("_")

    return " ".join(values)

# -----------------------------------------------------------------------------


text:
FROM ubuntu

COPY ./ /src
WORKDIR /src
RUN apt-get update

RUN apt-get -y install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libboost-all-dev wget bsdmainutils libevent-dev

RUN mkdir db4/

RUN wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
RUN tar -xzvf db-4.8.30.NC.tar.gz
WORKDIR /src/db-4.8.30.NC/build_unix/

RUN ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=/src/db4/
RUN make install

WORKDIR /src

RUN ./autogen.sh
RUN ./configure LDFLAGS="-L/src/db4/lib/" CPPFLAGS="-I/src/db4/include/"
RUN make
RUN cp src/plusonecoind /usr/bin
RUN cp src/plusonecoin-cli /usr/bin
RUN cp src/plusonecoin-tx /usr/bin
RUN rm -fr /src

redpajama_set_name: RedPajamaGithub


text:
import values from 'lodash/values';
import React from 'react';
import { connect } from 'react-redux';
import { pure } from 'recompose';

import Todo from './todo';
import { deleteTodo, toggleTodo, updateTodo } from '../modules/todos';

function stateToProps(state, props) {
  return {
    todos: values(state.todos).sort((a, b) => a.id - b.id),
    isEditing: state.ui.isEditing
  }
}

const dispatchToProps = {
  deleteTodo,
  toggleTodo,
  updateTodo
}

export class TodoList extends React.Component {
  render() {
    const { deleteTodo, isEditing, todos, toggleTodo, updateTodo } = this.props;

    return (
      <ul className="TodoList">
        {todos.map(todo =>
          <Todo
            todo={todo}
            initialValues={todo}
            isEditing={isEditing}
            key={todo.id}
            formKey={`${todo.id}`}
            onDelete={() => deleteTodo(todo.id)}
            onToggle={() => toggleTodo(todo.id)}
            onSubmit={attrs => updateTodo(todo.id, attrs)}
          />
        )}
      </ul>
    );
  }
}

export default pure(connect(stateToProps, dispatchToProps)(TodoList));


text:
#include <sstream>
#include <iostream>
#include <boost/lexical_cast.hpp>

#include "episodes_repository.h"
#include "podcasts_repository.h"

std::vector<Episode> retrievedEpisodesList;
Episode * episodeRetrievedById = nullptr;

EpisodesRepository::EpisodesRepository() = default;

EpisodesRepository::~EpisodesRepository() = default;

void EpisodesRepository::insert(Episode episode) {
    sqlite3 * database;
    char * errorMessage = 0;
    std::stringstream ss;
    int resultCode;

    long podcastId = episode.getPodcastId();
    verifyPodcastExists(podcastId);

    ss << "VALUES ('" << episode.getId() << "', "
            "'" << episode.getPodcastId() << "', "
            "'" << episode.getTitle() << "', "
            "'" << episode.getSummary() << "', "
            "'" << episode.getPublishDate() << "', "
            "'" << episode.getEnclosureUrl() << "', "
            "'" << episode.getDuration() << "' );";
    std::string sql = "INSERT INTO episodes (id, podcastId, title, summary, publishDate, enclosureUrl, duration) " + ss.str();

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    resultCode = sqlite3_exec(database, sql.c_str(), nullptr, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error inserting episode: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();
}

Episode EpisodesRepository::getById(boost::uuids::uuid & id) {
    sqlite3 * database;
    char * errorMessage = 0;
    int resultCode;

    std::stringstream ss;
    ss << "SELECT * FROM episodes WHERE id='" << id << "'";

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    resultCode = sqlite3_exec(database, ss.str().c_str(), getSingleCallback, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error retrieving episode by id: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();

    if (episodeRetrievedById == nullptr)
        throw "No episode with matching id found";

    boost::uuids::uuid retrievedId = episodeRetrievedById->getId();
    long retrievedPodcastId = episodeRetrievedById->getPodcastId();
    std::string retrievedTitle = episodeRetrievedById->getTitle();
    std::string retrievedSummary = episodeRetrievedById->getSummary();
    std::string retrievedPublishDate = episodeRetrievedById->getPublishDate();
    std::string retrievedEnclosureUrl = episodeRetrievedById->getEnclosureUrl();
    int retrievedDuration = episodeRetrievedById->getDuration();

    Episode e = Episode(retrievedId, retrievedPodcastId, retrievedTitle, retrievedSummary, retrievedPublishDate, retrievedEnclosureUrl, retrievedDuration);

    delete episodeRetrievedById;
    episodeRetrievedById = nullptr;

    return e;
}

std::vector<Episode> EpisodesRepository::getByPodcastId(long & id) {
    sqlite3 * database;
    char * errorMessage = 0;
    int resultCode;

    std::stringstream ss;
    ss << "SELECT * FROM episodes WHERE podcastId='" << id << "'";

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    retrievedEpisodesList = std::vector<Episode>();

    resultCode = sqlite3_exec(database, ss.str().c_str(), getListCallback, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error reading podcast episodes from db: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();

    return retrievedEpisodesList;
}

std::vector<Episode> EpisodesRepository::getAll() {
    sqlite3 * database;
    char * errorMessage = 0;
    int resultCode;
    char * sql = const_cast<char *>("SELECT * FROM episodes");

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    retrievedEpisodesList = std::vector<Episode>();

    resultCode = sqlite3_exec(database, sql, getListCallback, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error reading all episodes from db: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();

    return retrievedEpisodesList;
}

void EpisodesRepository::deleteById(boost::uuids::uuid & id) {
    sqlite3 * database;
    char * errorMessage = 0;
    int resultCode;

    std::stringstream ss;
    ss << "DELETE FROM episodes WHERE id='" << id << "'";

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    resultCode = sqlite3_exec(database, ss.str().c_str(), nullptr, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error deleting episode: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();
}

void EpisodesRepository::deleteByPodcastId(long & id) {
    sqlite3 * database;
    char * errorMessage = 0;
    int resultCode;

    std::stringstream ss;
    ss << "DELETE FROM episodes WHERE podcastId='" << id << "'";

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    resultCode = sqlite3_exec(database, ss.str().c_str(), nullptr, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error deleting podcast episodes: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();
}

void EpisodesRepository::deleteAll() {
    sqlite3 * database;
    char * errorMessage = 0;
    int resultCode;
    char * sql = const_cast<char *>("DELETE FROM episodes");

    databaseManager.openDatabase();
    database = databaseManager.getDatabase();

    resultCode = sqlite3_exec(database, sql, nullptr, nullptr, &errorMessage);
    if (resultCode != SQLITE_OK){
        std::stringstream ss;
        ss << "Error emptying episodes table: " << errorMessage << " (error code " << resultCode << ")";
        sqlite3_free(errorMessage);
        throw ss.str();
    }
    databaseManager.closeDatabase();
}

int EpisodesRepository::getListCallback(void *data, int argc, char **argv, char **columnName) {
    boost::uuids::uuid episodeId = boost::lexical_cast<boost::uuids::uuid>(argv[0]);
    long podcastId = atol(argv[1]);
    std::string episodeTitle = argv[2];
    std::string episodeSummary = argv[3];
    std::string episodePublishDate = argv[4];
    std::string episodeEnclosureUrl = argv[5];
    int episodeDuration = atoi(argv[5]);

    Episode episode = Episode(episodeId, podcastId, episodeTitle, episodeSummary, episodePublishDate, episodeEnclosureUrl, episodeDuration);
    retrievedEpisodesList.push_back(episode);

    return 0;
}

int EpisodesRepository::getSingleCallback(void *data, int argc, char **argv, char **columnName) {
    boost::uuids::uuid episodeId = boost::lexical_cast<boost::uuids::uuid>(argv[0]);
    long podcastId = atol(argv[1]);
    std::string episodeTitle = argv[2];
    std::string episodeSummary = argv[3];
    std::string episodePublishDate = argv[4];
    std::string episodeEnclosureUrl = argv[5];
    int episodeDuration = atoi(argv[5]);

    episodeRetrievedById = new Episode(episodeId, podcastId, episodeTitle, episodeSummary, episodePublishDate, episodeEnclosureUrl, episodeDuration);

    return 0;
}

bool EpisodesRepository::verifyPodcastExists(long & id) {
    PodcastsRepository podcastsRepository = PodcastsRepository();

    try {
        podcastsRepository.getById(id);
    }
    catch (const std::exception & ex) {
        std::stringstream ss;
        ss << "Podcast doesn't exist: " << *ex.what();
        throw ss.str();
    }

    return true;
}


text:
layout: post
title: "Wunder Weather Widget"
category: "Blog"
tags: [Widget,orchard,Weather,WunderWeather]
---
{% include JB/setup %}

I uploaded a new module to the [Orchard Gallery](http://www.orchardproject.net/gallery/Packages/Modules/Details/WunderWeather-1-0 "Orchard Gallery") today. The module is called Wunder Weather. It uses Wunderground's REST API to display the current weather.

You can install the the Widget by going to the admin section of your Orchard site, and clicking the Gallery > Modules menu item.

![](/Media/Default/BlogPost/blog/GalleryWidgets.jpg)

On the Module page find the WunderWeather Widget, and select the install link as pictured below.

![](/Media/Default/BlogPost/blog/WidgetInstaller.jpg)

Once the module has been installed, you will need to click on the Configuration > Features, and scroll down to the Widgets section. Then enable the WunderWeather Widget.

![](/Media/Default/BlogPost/blog/WidgetFeature.jpg)

Now that the widget has been enabled, you can add the widget to one of your layers by clicking on the Widgets. First you will need to select a layer you want to add the widget too.

![](/Media/Default/BlogPost/blog/wunder-weather-widget/WidgetLayer.jpg)

Once you have selected the layer, you will need to select the WeatherWidget.

![](/Media/Default/BlogPost/blog/wunder-weather-widget/AvailableWidgets.jpg)

Orchard will present you with a Widget form to fill out. Simply put in your airport location or zip code, and choose witch zone you want to display the widget.

![](/Media/Default/BlogPost/blog/wunder-weather-widget/WidgetSetup.jpg)

Once you click save, browse to the layer you placed the widget, and it should look like as follows.

![](/Media/Default/BlogPost/blog/WeatherWidget.jpg)


text:
q, u = dynamicsymbols('q u')

# The time derivatives of the symbols declared above
qd, ud = dynamicsymbols('q u', 1)

# The mass, length, and moment of inertia of the ladder and
# the acceleration due to gravity
m, l, g, Izz = symbols('m l g Izz')

# We define the inertial frame and a lean frame for the ladder
N = ReferenceFrame('N')
L = N.orientnew('L', 'Axis', [q, N.z])

# and then set the angular velocity of the lean frame in the inertial
# frame. The angular acceleration is automatically computed
L.set_ang_vel(N, u * N.z)

# Now the origin and the center of mass of the ladder are defined
O = Point('O')
A = Point('A')

# and we use the length and angle to locate the center of mass relative
# to the origin
A.set_pos(O, -l / 2 * cos(q) * N.x + l / 2 * sin(q) * N.y)

# Take the derivative of the position of the center of mass to get the
# corresponding velocity
O.set_vel(N, 0)
A.set_vel(N, l / 2 * u * sin(q) * N.x + l / 2 * u * cos(q) * N.y)

# The ladder can now be defined as a rigid body
ladder = RigidBody('ladder', A, L, m, (inertia(L, 0, 0, Izz), A))

# Set up all the inputs to Kanes Method
kd = [u - qd]
bodyList = [ladder]
forceList = [(A, -m * g * N.y)]

# Finally we solve the dynamics
KM = KanesMethod(N, q_ind = [q], u_ind = [u], kd_eqs = kd)
KM.kanes_equations(forceList, bodyList)

# The mass matrix and the forcing function can be taken out of the
# Kanes Method object KM
MM = KM.mass_matrix
forcing = KM.forcing

# and those can be used to find the equations of motion
rhs = MM.inv() * forcing
kdd = KM.kindiffdict()

rhs = rhs.subs(kdd)
rhs.simplify()


text:
package beaform;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.concurrent.TimeUnit;

import org.junit.Test;

import beaform.commands.Command;
import beaform.commands.CommandExecutor;

public class CommandHandlerTest {

	@Test
	public void testCommandHandler() throws InterruptedException {
		CommandExecutor commandExec = CommandExecutor.getInstance();

		MockCommand command = new MockCommand();
		commandExec.execute(command);
		commandExec.shutdown();
		commandExec.awaitTermination(5,TimeUnit.SECONDS);
		assertEquals("This method was not executed as many time as it should", 1, command.getTimesExecuted());
		assertTrue("The command executer is not shut down", commandExec.isTerminated());
	}

	public final class MockCommand implements Command {
		private volatile int timesExecuted = 0;

		public int getTimesExecuted() {
			return this.timesExecuted;
		}

		@Override
		public void execute() {
			this.timesExecuted++;
		}
	}

}


text:
<?php

namespace Anastaszor\Slugify;

/**
 * RangeFactory class file.
 *
 * This class builds the ranges objects by getting the data files from their
 * folder.
 *
 * @author Anastaszor
 */
class RangeFactory implements IRangeFactory
{

	/**
	 * Cache for all file names that are available into the lib.
	 *
	 * @var string[]
	 */
	private static $_files = array();

	/**
	 * Cache for all the ranges that were loaded until then.
	 *
	 * @var IUtf8Range[]
	 */
	private static $_ranges = array();

	/**
	 * {@inheritDoc}
	 * @see \Anastaszor\Slugify\IRangeFactory::getRangeFromUtf8Code()
	 */
	public function getRangeFromUtf8Code($utf8code)
	{
		$matches = array();
		$code = strtoupper($utf8code);
		if(preg_match('#U\+([0-9A-F]{4,8})#u', $code, $matches))
		{
			return $this->getLowerRangeFromHexaCode($matches[1]);
		}
		else throw new IllegalArgumentException(
			'Invalid utf8 hexadecimal code "'.$utf8code.'", it should be in the form of "U+xxxx".'
		);
	}

	/**
	 * {@inheritDoc}
	 * @see \Anastaszor\Slugify\IRangeFactory::getRangeFromChar()
	 */
	public function getRangeFromChar($char)
	{
		switch(strlen($char))
		{
			case 1:
				// TODO: Auto-generated method stub
			case 2:
				// TODO: Auto-generated method stub
			case 3:
				// TODO: Auto-generated method stub
			case 4:
				// TODO: Auto-generated method stub
			case 5:
				// TODO: Auto-generated method stub
			case 6:
				// TODO: Auto-generated method stub
			case 7:
				// TODO: Auto-generated method stub
			case 8:
				// TODO: Auto-generated method stub
		}

		throw new IllegalArgumentException(
			'The given character string "'.$char.'" is not a valid utf8 character.'
		);
	}

	/**
	 * {@inheritDoc}
	 * @see \Anastaszor\Slugify\IRangeFactory::getRangeFromName()
	 */
	public function getRangeFromName($name)
	{
		return $this->getRangeFromFileName($name);
	}

	/**
	 * {@inheritDoc}
	 * @see \Anastaszor\Slugify\IRangeFactory::getRangesFromScript()
	 */
	public function getRangesFromScript(array $script)
	{
		$ranges = array();
		foreach($script as $filename)
		{
			$ranges[] = $this->getRangeFromFileName($filename);
		}
		return $ranges;
	}

	/**
	 * Gets the range file which contains the character represented by this
	 * hexa code.
	 *
	 * @param string $hexacode
	 * @return Utf8Range
	 */
	protected function getLowerRangeFromHexaCode($hexacode)
	{
		if(self::$_files === array())
		{
			$dirit = new \FilesystemIterator($this->getBasePhpPath(), \FilesystemIterator::SKIP_DOTS);
			foreach($dirit as $filename)
			{
				$matches = array();
				if(preg_match('#^U\+([A-F0-9]{4,8})#', $filename, $matches))
				{
					self::$_files[hexdec($matches[1])] = $filename;
				}
				else throw new IllegalArgumentException(
					'Impossible to parse file name "'.$filename.'". Please reinstall the php-slugify library.'
				);
			}
		}

		if(count(self::$_files) === 0)
		{
			throw new IllegalArgumentException(
				'Impossible to find files for the hexa code "'.$hexacode.'". Please reinstall the php-slugify library.'
			);
		}

		$numericalValue = hexdec($hexacode);
		$currentValue = 0;
		$file = null;

		foreach(self::$_files as $fileval => $filename)
		{
			if($fileval > $currentValue && $fileval <= $numericalValue)
			{
				$currentValue = $fileval;
				$file = $filename;
			}
		}

		if($file === null)
		{
			throw new IllegalArgumentException(
				'Impossible to find file for the hexa code "'.$hexacode.'". Please reinstall the php-slugify library.'
			);
		}

		return $this->getRangeFromFileName($filename);
	}

	/**
	 * Gets the range file from its name (which should be a string with format
	 * like "U+xxxx-U+xxxx".
	 *
	 * @param string $filename
	 * @return Utf8Range
	 * @throws FileNotFoundException if the file does not exists.
	 */
	protected function getRangeFromFileName($filename)
	{
		if(isset(self::$_ranges[$filename]))
			return self::$_ranges[$filename];

		$fullPath = $this->getBasePhpPath().DIRECTORY_SEPARATOR.$filename.'.php';

		return self::$_ranges[$filename] = new Utf8Range($fullPath);
	}

	/**
	 * Gets the php directory where all unicode php array files are stored.
	 *
	 * @return string
	 */
	protected function getBasePhpPath()
	{
		return dirname(dirname(__DIR__)).DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'php';
	}

}


text:
package com.dovan.neotimelogger;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;

import java.io.File;

/**
 * Created by dovan on 10/24/16.
 */

public class FileDeleteDialog extends DialogFragment {
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        //SORRYIMNOTSORRY
        AlertDialog.Builder bob = new AlertDialog.Builder(getActivity());
        bob.setMessage(R.string.Overwrite)
                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Context context = getActivity();
                        File file = new File(context.getFilesDir(), "Autogen.txt");
                        if(file.delete()){
                        Intent intent = new Intent(context, Add.class);
                        startActivity(intent);}
                        else{

                        }
                    }
                })
                .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                     dismiss();
                    }
                });
        return bob.create();
    }
}


text:
import { Component } from '@angular/core';

@Component({
    template: `

This is not the page you were looking for!

    `
})
export class PageNotFoundComponent { }


text:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--                                                                -->
<!--   W4F: Copyright Arnaud Sahuguet and Fabien Azavant, 1998-99   -->
<!--   URL: http://db.cis.upenn.edu/W4F                             -->
<!--                                                                -->
<!DOCTYPE W4F_DOC  SYSTEM "movies.dtd">
<W4F_DOC>
  <Movie>
    <Title>Duck Soup</Title>
    <Year>1933</Year>
    <Directed_By>
      <Director>Leo McCarey</Director>
    </Directed_By>
    <Genres>
      <Genre>Comedy</Genre>
      <Genre>Musical</Genre>
      <Genre>(more)</Genre>
    </Genres>
    <Cast>
      <Actor>
        <FirstName>Groucho</FirstName>
        <LastName>Marx</LastName>
      </Actor>
      <Actor>
        <FirstName>Harpo</FirstName>
        <LastName>Marx</LastName>
      </Actor>
      <Actor>
        <FirstName>Chico</FirstName>
        <LastName>Marx</LastName>
      </Actor>
      <Actor>
        <FirstName>Zeppo</FirstName>
        <LastName>Marx</LastName>
      </Actor>
      <Actor>
        <FirstName>Margaret</FirstName>
        <LastName>Dumont</LastName>
      </Actor>
      <Actor>
        <FirstName>Raquel</FirstName>
        <LastName>Torres</LastName>
      </Actor>
      <Actor>
        <FirstName>Louis</FirstName>
        <LastName>Calhern</LastName>
      </Actor>
      <Actor>
        <FirstName>Edmund</FirstName>
        <LastName>Breese</LastName>
      </Actor>
      <Actor>
        <FirstName>Leonid</FirstName>
        <LastName>Kinskey</LastName>
      </Actor>
      <Actor>
        <FirstName>Charles</FirstName>
        <LastName>Middleton (I)</LastName>
      </Actor>
      <Actor>
        <FirstName>Verna</FirstName>
        <LastName>Hillie</LastName>
      </Actor>
      <Actor>
        <FirstName>George</FirstName>
        <LastName>MacQuarrie</LastName>
      </Actor>
      <Actor>
        <FirstName>Edgar</FirstName>
        <LastName>Kennedy</LastName>
      </Actor>
      <Actor>
        <FirstName>Edwin</FirstName>
        <LastName>Maxwell</LastName>
      </Actor>
      <Actor>
        <FirstName>William</FirstName>
        <LastName>Worthington</LastName>
      </Actor>
    </Cast>
  </Movie>
</W4F_DOC>


text:
<?php
/**
 * XAlphaListPager class file.
 *
 * Strongly based on Qiang Xues {@link CListPager} from yiiframework.
 *
 * @author Jascha Koch
 * @license http://www.yiiframework.com/license/
 * @version 1.2
 */
class XAlphaListPager extends CBasePager
{
	/**
	 * @var string the text label for the 'SHOW ALL'-button. Defaults to 'All'.
	 */
	public $allPageLabel;
	/**
	 * @var bool show the 'SHOW All'-button. Defaults to true.
	 */
	public $showAllPage=true;
	/**
	 * @var string the text label for the 'SHOW NUMERIC'-button. Defaults to '0-9'.
	 */
	public $numPageLabel;
	/**
	 * @var bool show the 'SHOW NUMERIC'-button. Defaults to false.
	 */
	public $showNumPage=false;
	/**
	 * @var string the text displayed as a prompt option in the dropdown list. Defaults to null, meaning no prompt.
	 */
	public $promptText;
	/**
	 * @var string the format string used to generate page selection text.
	 * The sprintf function will be used to perform the formatting.
	 */
	public $pageTextFormat;
	/**
	 * @var string the text shown before page buttons. Defaults to 'Go to letter: '.
	 */
	public $header;
	/**
	 * @var string the text shown after page buttons.
	 */
	public $footer='';
	/**
	 * @var array HTML attributes for the pager container tag.
	 */
	public $htmlOptions=array();

	/**
	 * Initializes the pager by setting some default property values.
	 */
	public function init()
	{
		if($this->allPageLabel===null)
			$this->allPageLabel=Yii::t('ui','All');
		if($this->numPageLabel===null)
			$this->numPageLabel=Yii::t('ui','0-9');
		if($this->header===null)
			$this->header=Yii::t('ui','Go to letter: ');

		if(!isset($this->htmlOptions['id']))
			$this->htmlOptions['id']=$this->getId();
		if($this->promptText!==null)
			$this->htmlOptions['prompt']=$this->promptText;
		if(!isset($this->htmlOptions['onchange']))
			$this->htmlOptions['onchange']="if(this.value!='') {window.location=this.value;};";
	}

	/**
	 * Executes the widget.
	 * This overrides the parent implementation by displaying the generated page buttons.
	 */
	public function run()
	{
		$labels_comp = $labels = $this->pages->getCharSet();
		$activeLabels_comp = $activeLabels = $this->pages->getActiveCharSet();
		$labelCount = count($labels);
		$currentPage=$this->getCurrentPage(false);

		if($labelCount<=1)
			return;
		$pages=array();
		$disabledOptions=array();

		if($this->pages->forceCaseInsensitive===true){
			// convert all labels (characters) to lower case for case insensitive comparison
			$labels_comp = array_map('mb_strtolower',$labels);
			$activeLabels_comp = array_map('mb_strtolower',$activeLabels);
		}

		if($this->showAllPage){
			$pages[$this->createPageUrl(-1)]=$this->allPageLabel;
			if(!count($activeLabels)>0)
				$disabledOptions[$this->createPageUrl(-1)] = array('disabled'=>true);
		}

		if($this->showNumPage){
			$pages[$this->createPageUrl(0)]=$this->numPageLabel;
			if(!$this->pages->activeNumbers)
				$disabledOptions[$this->createPageUrl(0)] = array('disabled'=>true);
		}

		for($i=0;$i<$labelCount;++$i)
		{
			$pages[$this->createPageUrl($i+1)]=$this->generatePageText($labels[$i]);
			if(!in_array($labels_comp[$i],$activeLabels_comp))
				$disabledOptions[$this->createPageUrl($i+1)] = array('disabled'=>true);
		}

		if(!empty($disabledOptions))
			$this->htmlOptions['options'] = array_merge((array)$this->htmlOptions['options'],$disabledOptions);

		$selection=$this->createPageUrl($currentPage);
		echo $this->header;
		echo CHtml::dropDownList($this->getId(),$selection,$pages,$this->htmlOptions);
		echo $this->footer;
	}

	/**
	 * Generates the list option for the specified page number.
	 * You may override this method to customize the option display.
	 * @param string page character
	 * @return string the list option for the page character
	 */
	protected function generatePageText($label)
	{
		if($this->pageTextFormat!==null)
			return sprintf($this->pageTextFormat,$label);
		else
			return $label;
	}
}
?>


text:
define([
	'../_StoreMixin',
	'dojo/_base/declare',
	'dojo/_base/array',
	'dojo/_base/lang',
	'dojo/dom-construct',
	'dojo/dom-class',
	'dojo/on',
	'dojo/query',
	'dojo/string',
	'dojo/has',
	'dojo/when',
	'../util/misc',
	'dojo/i18n!./nls/pagination',
	'dojo/_base/sniff'
], function (_StoreMixin, declare, arrayUtil, lang, domConstruct, domClass, on, query, string, has, when,
		miscUtil, i18n) {
	function cleanupContent(grid) {
		// Remove any currently-rendered rows, or noDataMessage
		if (grid.noDataNode) {
			domConstruct.destroy(grid.noDataNode);
			delete grid.noDataNode;
		}
		else {
			grid.cleanup();
		}
		grid.contentNode.innerHTML = '';
	}
	function cleanupLoading(grid) {
		if (grid.loadingNode) {
			domConstruct.destroy(grid.loadingNode);
			delete grid.loadingNode;
		}
		else if (grid._oldPageNodes) {
			// If cleaning up after a load w/ showLoadingMessage: false,
			// be careful to only clean up rows from the old page, not the new one
			for (var id in grid._oldPageNodes) {
				grid.removeRow(grid._oldPageNodes[id]);
			}
			delete grid._oldPageNodes;
		}
		delete grid._isLoading;
	}

	return declare(_StoreMixin, {
		// summary:
		//		An extension for adding discrete pagination to a List or Grid.

		// rowsPerPage: Number
		//		Number of rows (items) to show on a given page.
		rowsPerPage: 10,

		// pagingTextBox: Boolean
		//		Indicates whether or not to show a textbox for paging.
		pagingTextBox: false,
		// previousNextArrows: Boolean
		//		Indicates whether or not to show the previous and next arrow links.
		previousNextArrows: true,
		// firstLastArrows: Boolean
		//		Indicates whether or not to show the first and last arrow links.
		firstLastArrows: false,

		// pagingLinks: Number
		//		The number of page links to show on each side of the current page
		//		Set to 0 (or false) to disable page links.
		pagingLinks: 2,
		// pageSizeOptions: Array[Number]
		//		This provides options for different page sizes in a drop-down.
		//		If it is empty (default), no page size drop-down will be displayed.
		pageSizeOptions: null,

		// showLoadingMessage: Boolean
		//		If true, clears previous data and displays loading node when requesting
		//		another page; if false, leaves previous data in place until new data
		//		arrives, then replaces it immediately.
		showLoadingMessage: true,

		// i18nPagination: Object
		//		This object contains all of the internationalized strings as
		//		key/value pairs.
		i18nPagination: i18n,

		showFooter: true,
		_currentPage: 1,

		buildRendering: function () {
			this.inherited(arguments);

			// add pagination to footer
			var grid = this,
				paginationNode = this.paginationNode =
					domConstruct.create('div', { className: 'dgrid-pagination' }, this.footerNode),
				statusNode = this.paginationStatusNode =
					domConstruct.create('div', { className: 'dgrid-status' }, paginationNode),
				i18n = this.i18nPagination,
				navigationNode,
				node;

			statusNode.tabIndex = 0;

			// Initialize UI based on pageSizeOptions and rowsPerPage
			this._updatePaginationSizeSelect();
			this._updateRowsPerPageOption();

			// initialize some content into paginationStatusNode, to ensure
			// accurate results on initial resize call
			this._updatePaginationStatus(this._total);

			navigationNode = this.paginationNavigationNode =
				domConstruct.create('div', { className: 'dgrid-navigation' }, paginationNode);

			if (this.firstLastArrows) {
				// create a first-page link
				node = this.paginationFirstNode = domConstruct.create('span', {
					'aria-label': i18n.gotoFirst,
					className: 'dgrid-first dgrid-page-link',
					innerHTML: '«',
					tabIndex: 0
				}, navigationNode);
			}
			if (this.previousNextArrows) {
				// create a previous link
				node = this.paginationPreviousNode = domConstruct.create('span', {
					'aria-label': i18n.gotoPrev,
					className: 'dgrid-previous dgrid-page-link',
					innerHTML: '‹',
					tabIndex: 0
				}, navigationNode);
			}

			this.paginationLinksNode = domConstruct.create('span', {
				className: 'dgrid-pagination-links'
			}, navigationNode);

			if (this.previousNextArrows) {
				// create a next link
				node = this.paginationNextNode = domConstruct.create('span', {
					'aria-label': i18n.gotoNext,
					className: 'dgrid-next dgrid-page-link',
					innerHTML: '›',
					tabIndex: 0
				}, navigationNode);
			}
			if (this.firstLastArrows) {
				// create a last-page link
				node = this.paginationLastNode = domConstruct.create('span', {
					'aria-label': i18n.gotoLast,
					className: 'dgrid-last dgrid-page-link',
					innerHTML: '»',
					tabIndex: 0
				}, navigationNode);
			}

			/* jshint maxlen: 121 */
			this._listeners.push(on(navigationNode, '.dgrid-page-link:click,.dgrid-page-link:keydown', function (event) {
				// For keyboard events, only respond to enter
				if (event.type === 'keydown' && event.keyCode !== 13) {
					return;
				}

				var cls = this.className,
					curr, max;

				if (grid._isLoading || cls.indexOf('dgrid-page-disabled') > -1) {
					return;
				}

				curr = grid._currentPage;
				max = Math.ceil(grid._total / grid.rowsPerPage);

				// determine navigation target based on clicked link's class
				if (this === grid.paginationPreviousNode) {
					grid.gotoPage(curr - 1);
				}
				else if (this === grid.paginationNextNode) {
					grid.gotoPage(curr + 1);
				}
				else if (this === grid.paginationFirstNode) {
					grid.gotoPage(1);
				}
				else if (this === grid.paginationLastNode) {
					grid.gotoPage(max);
				}
				else if (cls === 'dgrid-page-link') {
					grid.gotoPage(+this.innerHTML); // the innerHTML has the page number
				}
			}));
		},

		destroy: function () {
			this.inherited(arguments);
			if (this._pagingTextBoxHandle) {
				this._pagingTextBoxHandle.remove();
			}
		},

		_updatePaginationSizeSelect: function () {
			// summary:
			//		Creates or repopulates the pagination size selector based on
			//		the values in pageSizeOptions. Called from buildRendering
			//		and _setPageSizeOptions.

			var pageSizeOptions = this.pageSizeOptions,
				paginationSizeSelect = this.paginationSizeSelect,
				handle;

			if (pageSizeOptions && pageSizeOptions.length) {
				if (!paginationSizeSelect) {
					// First time setting page options; create the select
					paginationSizeSelect = this.paginationSizeSelect = domConstruct.create('select', {
						'aria-label': this.i18nPagination.rowsPerPage,
						className: 'dgrid-page-size'
					}, this.paginationNode);

					handle = this._paginationSizeChangeHandle =
						on(paginationSizeSelect, 'change', lang.hitch(this, function () {
							this.set('rowsPerPage', +this.paginationSizeSelect.value);
						}));
					this._listeners.push(handle);
				}

				// Repopulate options
				paginationSizeSelect.options.length = 0;
				for (var i = 0; i < pageSizeOptions.length; i++) {
					domConstruct.create('option', {
						innerHTML: pageSizeOptions[i],
						selected: this.rowsPerPage === pageSizeOptions[i],
						value: pageSizeOptions[i]
					}, paginationSizeSelect);
				}
				// Ensure current rowsPerPage value is in options
				this._updateRowsPerPageOption();
			}
			else if (!(pageSizeOptions && pageSizeOptions.length) && paginationSizeSelect) {
				// pageSizeOptions was removed; remove/unhook the drop-down
				domConstruct.destroy(paginationSizeSelect);
				this.paginationSizeSelect = null;
				this._paginationSizeChangeHandle.remove();
			}
		},

		_setPageSizeOptions: function (pageSizeOptions) {
			this.pageSizeOptions = pageSizeOptions && pageSizeOptions.sort(function (a, b) {
				return a - b;
			});
			this._updatePaginationSizeSelect();
		},

		_updateRowsPerPageOption: function () {
			// summary:
			//		Ensures that an option for rowsPerPage's value exists in the
			//		paginationSizeSelect drop-down (if one is rendered).
			//		Called from buildRendering and _setRowsPerPage.

			var rowsPerPage = this.rowsPerPage,
				pageSizeOptions = this.pageSizeOptions,
				paginationSizeSelect = this.paginationSizeSelect;

			if (paginationSizeSelect) {
				if (arrayUtil.indexOf(pageSizeOptions, rowsPerPage) < 0) {
					this._setPageSizeOptions(pageSizeOptions.concat([rowsPerPage]));
				}
				else {
					paginationSizeSelect.value = '' + rowsPerPage;
				}
			}
		},

		_setRowsPerPage: function (rowsPerPage) {
			this.rowsPerPage = rowsPerPage;
			this._updateRowsPerPageOption();
			this.gotoPage(1);
		},

		_updateNavigation: function (total) {
			// summary:
			//		Update status and navigation controls based on total count from query

			var grid = this,
				i18n = this.i18nPagination,
				linksNode = this.paginationLinksNode,
				currentPage = this._currentPage,
				pagingLinks = this.pagingLinks,
				paginationNavigationNode = this.paginationNavigationNode,
				end = Math.ceil(total / this.rowsPerPage),
				pagingTextBoxHandle = this._pagingTextBoxHandle,
				focused = document.activeElement,
				focusedPage,
				lastFocusablePageLink,
				focusableNodes;

			function pageLink(page, addSpace) {
				var link;
				var disabled;
				if (grid.pagingTextBox && page === currentPage && end > 1) {
					// use a paging text box if enabled instead of just a number
					link = domConstruct.create('input', {
						'aria-label': i18n.jumpPage,
						className: 'dgrid-page-input',
						type: 'text',
						value: currentPage
					}, linksNode);
					grid._pagingTextBoxHandle = on(link, 'change', function () {
						var value = +this.value;
						if (!isNaN(value) && value > 0 && value <= end) {
							grid.gotoPage(+this.value);
						}
					});
					if (focused && focused.tagName === 'INPUT') {
						link.focus();
					}
				}
				else {
					// normal link
					disabled = page === currentPage;
					link = domConstruct.create('span', {
						'aria-label': i18n.gotoPage,
						className: 'dgrid-page-link' + (disabled ? ' dgrid-page-disabled' : ''),
						innerHTML: page + (addSpace ? ' ' : ''),
						tabIndex: disabled ? -1 : 0
					}, linksNode);

					// Try to restore focus if applicable;
					// if we need to but can't, try on the previous or next page,
					// depending on whether we're at the end
					if (focusedPage === page) {
						if (!disabled) {
							link.focus();
						}
						else if (page < end) {
							focusedPage++;
						}
						else {
							lastFocusablePageLink.focus();
						}
					}

					if (!disabled) {
						lastFocusablePageLink = link;
					}
				}
			}

			function setDisabled(link, disabled) {
				domClass.toggle(link, 'dgrid-page-disabled', disabled);
				link.tabIndex = disabled ? -1 : 0;
			}

			function addSkipNode() {
				// Adds visual indication of skipped page numbers in navigation area
				domConstruct.create('span', {
					className: 'dgrid-page-skip',
					innerHTML: '...'
				}, linksNode);
			}

			if (!focused || !this.paginationNavigationNode.contains(focused)) {
				focused = null;
			}
			else if (focused.className === 'dgrid-page-link') {
				focusedPage = +focused.innerHTML;
			}

			if (pagingTextBoxHandle) {
				pagingTextBoxHandle.remove();
			}
			linksNode.innerHTML = '';
			query('.dgrid-first, .dgrid-previous', paginationNavigationNode).forEach(function (link) {
				setDisabled(link, currentPage === 1);
			});
			query('.dgrid-last, .dgrid-next', paginationNavigationNode).forEach(function (link) {
				setDisabled(link, currentPage >= end);
			});

			if (pagingLinks && end > 0) {
				// always include the first page (back to the beginning)
				pageLink(1, true);
				var start = currentPage - pagingLinks;
				if (start > 2) {
					addSkipNode();
				}
				else {
					start = 2;
				}
				// now iterate through all the page links we should show
				for (var i = start; i < Math.min(currentPage + pagingLinks + 1, end); i++) {
					pageLink(i, true);
				}
				if (currentPage + pagingLinks + 1 < end) {
					addSkipNode();
				}
				// last link
				if (end > 1) {
					pageLink(end);
				}
			}
			else if (grid.pagingTextBox) {
				// The pageLink function is also used to create the paging textbox.
				pageLink(currentPage);
			}

			if (focused && focused.tabIndex === -1) {
				// One of the first/last or prev/next links was focused but
				// is now disabled, so find something focusable
				focusableNodes = query('[tabindex="0"]', this.paginationNavigationNode);
				if (focused === this.paginationPreviousNode || focused === this.paginationFirstNode) {
					focused = focusableNodes[0];
				}
				else if (focusableNodes.length) {
					focused = focusableNodes[focusableNodes.length - 1];
				}
				if (focused) {
					focused.focus();
				}
			}
		},

		_updatePaginationStatus: function (total) {
			var count = this.rowsPerPage;
			var start = Math.min(total, (this._currentPage - 1) * count + 1);
			this.paginationStatusNode.innerHTML = string.substitute(this.i18nPagination.status, {
				start: start,
				end: Math.min(total, start + count - 1),
				total: total
			});
		},

		refresh: function (options) {
			// summary:
			//		Re-renders the first page of data, or the current page if
			//		options.keepCurrentPage is true.

			var self = this;
			var page = options && options.keepCurrentPage ?
				Math.min(this._currentPage, Math.ceil(this._total / this.rowsPerPage)) : 1;

			this.inherited(arguments);

			// Reset to first page and return promise from gotoPage
			return this.gotoPage(page).then(function (results) {
				// Emit on a separate turn to enable event to be used consistently for
				// initial render, regardless of whether the backing store is async
				setTimeout(function () {
					on.emit(self.domNode, 'dgrid-refresh-complete', {
						bubbles: true,
						cancelable: false,
						grid: self
					});
				}, 0);

				return results;
			});
		},

		_onNotification: function (rows, event, collection) {
			var rowsPerPage = this.rowsPerPage;
			var pageEnd = this._currentPage * rowsPerPage;
			var needsRefresh = (event.type === 'add' && event.index < pageEnd) ||
				(event.type === 'delete' && event.previousIndex < pageEnd) ||
				(event.type === 'update' &&
					Math.floor(event.index / rowsPerPage) !== Math.floor(event.previousIndex / rowsPerPage));

			if (needsRefresh) {
				// Refresh the current page to maintain correct number of rows on page
				this.gotoPage(Math.min(this._currentPage, Math.ceil(event.totalLength / this.rowsPerPage)) || 1);
			}
			// If we're not updating the whole page, check if we at least need to update status/navigation
			else if (collection === this._renderedCollection && event.totalLength !== this._total) {
				this._updatePaginationStatus(event.totalLength);
				this._updateNavigation(event.totalLength);
			}
		},

		renderQueryResults: function (results, beforeNode) {
			var grid = this,
				rows = this.inherited(arguments);

			if (!beforeNode) {
				if (this._topLevelRequest) {
					// Cancel previous async request that didn't finish
					this._topLevelRequest.cancel();
					delete this._topLevelRequest;
				}

				if (typeof rows.cancel === 'function') {
					// Store reference to new async request in progress
					this._topLevelRequest = rows;
				}

				rows.then(function () {
					if (grid._topLevelRequest) {
						// Remove reference to request now that it's finished
						delete grid._topLevelRequest;
					}
				});
			}

			return rows;
		},

		insertRow: function () {
			var oldNodes = this._oldPageNodes,
				row = this.inherited(arguments);

			if (oldNodes && row === oldNodes[row.id]) {
				// If the previous row was reused, avoid removing it in cleanup
				delete oldNodes[row.id];
			}

			return row;
		},

		gotoPage: function (page) {
			// summary:
			//		Loads the given page.  Note that page numbers start at 1.
			var grid = this,
				start = (this._currentPage - 1) * this.rowsPerPage;

			if (!this._renderedCollection) {
				console.warn('Pagination requires a collection to operate.');
				return when([]);
			}

			if (this._renderedCollection.releaseRange) {
				this._renderedCollection.releaseRange(start, start + this.rowsPerPage);
			}

			return this._trackError(function () {
				var count = grid.rowsPerPage,
					start = (page - 1) * count,
					options = {
						start: start,
						count: count
					},
					results,
					contentNode = grid.contentNode,
					loadingNode,
					oldNodes,
					children,
					i,
					len;

				if (grid.showLoadingMessage) {
					cleanupContent(grid);
					loadingNode = grid.loadingNode = domConstruct.create('div', {
						className: 'dgrid-loading',
						innerHTML: grid.loadingMessage
					}, contentNode);
				}
				else {
					// Reference nodes to be cleared later, rather than now;
					// iterate manually since IE < 9 doesn't like slicing HTMLCollections
					grid._oldPageNodes = oldNodes = {};
					children = contentNode.children;
					for (i = 0, len = children.length; i < len; i++) {
						oldNodes[children[i].id] = children[i];
					}
				}

				// set flag to deactivate pagination event handlers until loaded
				grid._isLoading = true;

				results = grid._renderedCollection.fetchRange({
					start: start,
					end: start + count
				});

				return grid.renderQueryResults(results, null, options).then(function (rows) {
					cleanupLoading(grid);
					// Reset scroll Y-position now that new page is loaded.
					grid.scrollTo({ y: 0 });

					if (grid._rows) {
						grid._rows.min = start;
						grid._rows.max = start + count - 1;
					}

					results.totalLength.then(function (total) {
						if (!total) {
							if (grid.noDataNode) {
								domConstruct.destroy(grid.noDataNode);
								delete grid.noDataNode;
							}
							// If there are no results, display the no data message.
							grid.noDataNode = domConstruct.create('div', {
								className: 'dgrid-no-data',
								innerHTML: grid.noDataMessage
							}, grid.contentNode);
						}

						// Update status text based on now-current page and total.
						grid._total = total;
						grid._currentPage = page;
						grid._rowsOnPage = rows.length;
						grid._updatePaginationStatus(total);

						// It's especially important that _updateNavigation is called only
						// after renderQueryResults is resolved as well (to prevent jumping).
						grid._updateNavigation(total);
					});

					return results;
				}, function (error) {
					cleanupLoading(grid);
					throw error;
				});
			});
		}
	});
});


text:
.clearfix:after {
	visibility: hidden;
	display: block;
	font-size: 0;
	content: " ";
	clear: both;
	height: 0;
}

.destination {
	padding: 10px;
}

.bb-dest {
	background: #ECECEC;
	margin: 0;
	display: block;
	border-radius: 5px;
	padding: 10px 10px 0 10px;
	margin-bottom: 40px;
	border-radius: 5px;
	border: 1px solid #d6d6d6;
	border-top: 1px solid #ebebeb;
	box-shadow: 0px 3px 0px 0px #aaaaaa;
	box-shadow: 0px 3px 0px 0px #CFCFCF;
	font-size: auto;
}
h3 {
	margin: 6px 0 10px 5px;
	font-weight: 200;
	font-size: 20px;
	font-family: "HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",sans-serif;
	color: #464646;
}
.bb-dest-option .info {
	display: block;
	background: #fff;
	border: 1px solid #e7e7e7;
	border-top: 1px solid #ebebeb;
	border-bottom: 1px solid #c9c9c9;
	border-radius: 4px 0 0 4px;
	//padding: 15px 20px 15px 15px;
	padding: 15px 1%;
	margin-bottom: 10px;
	text-decoration: none;
	color: #252525;
	float: left;
	width: 90%;
	line-height: 2;
}
.bb-dest-option .info.add-new {
	width: 95%;
	padding-right: 3%;
	border-radius: 4px;
}
.bb-dest-option .info.added:hover {
	color: #da2828;
}
.bb-dest-option .info.added:active, .bb-dest-option .info.added:focus {
	box-shadow: inset 0 0 5px #da2828;
}
.bb-dest-option .info .type {
	display: block;
	float: left;
	min-width: 150px;
	margin-right: 20px;
	padding-right: 20px;
	border-right: 1px solid #ebebeb;
	line-height: 32px;
	font-size: medium;
}
.bb-dest-option .info .bb-dest-name {
	font-weight: bold;
	line-height: 32px;
	font-size: medium;
}
.bb-dest-option .info .bb-dest-desc {
	font-size: 14px;
	line-height: 1.5;
	color: #666;
	display: block;
	margin: 16px 0 0;
}
.bb-dest-option .icon {
	width: 32px;
	height: 32px;
	display: block;
	float: left;
	margin-right: 20px;
}

.bb-dest-option .info .icon.plus {background: transparent url('addplus.png') top left no-repeat;}

.bb-dest-option .info:hover .icon.email, .bb-dest-option .info:active .icon.email,
.bb-dest-option .info.added:hover .icon.amazon, .bb-dest-option .info.added:active .icon.amazon,
.bb-dest-option .info.added:hover .icon.dropbox, .bb-dest-option .info.added:active .icon.dropbox,
.bb-dest-option .info.added:hover .icon.ftp, .bb-dest-option .info.added:active .icon.ftp,
.bb-dest-option .info.added:hover .icon.rackspace, .bb-dest-option .info.added:active .icon.rackspace,
.bb-dest-option .info.added:hover .icon.local, .bb-dest-option .info.added:active .icon.local {
	background-position: bottom left;
}

.bb-dest-option .optionicon {
	display: block;
	float: left;
	height: 40px;
	/*
	width: 20px;
	padding: 11px;
	*/
	padding: 11px 1%;
	width: 5%;
	margin-top: 0;
	background-size: 20px 20px;
	border-radius: 0 4px 4px 0;
	border-right: 1px solid #e7e7e7;
	border-top: 1px solid #ebebeb;
	border-bottom: 1px solid #c9c9c9;
}
.bb-dest-option .optionicon.open {
	background-position: center;
	background-repeat:no-repeat;
	background-color: #fff;
	background-size: 20px 20px;
}
 .bb-dest-option .optionicon.dest-add {
	font-size: 34px;
	text-align: center;
	line-height: 1;
	color: #252525;
	margin: 0;
	text-decoration: none;
}
.bb-dest-option .optionicon.open:hover {
	background-color: #a8a8a8;
	background-size: 20px 20px;
	box-shadow: inset 0 0 8px #666;
}
.bb-dest-option .settings.add-new:before {
	margin-left: 515px;
}
.bb-dest-option .settings {
	display: block;
	clear: both;
	display: none;
}
.bb-dest-option .settings-inside {
	display: block;
	background: #fff;
	border: 1px solid #e7e7e7;
	border-bottom: 1px solid #d6d6d6;
	border-top: none;
	border-radius: 4px;
	padding: 20px 30px;
	margin-bottom: 30px;
}
.new-dest-name {
	font-size: 18px;
	border: 1px solid #ebebeb;
	padding: 2px;
}

.settings-inside .settings-field {
	display: block;
	margin: 10px 0;
}
.settings-inside label, .settings-inside th {
	font-size: 14px;
	min-width: 160px;
	//margin: 20px 20px 0 0;
	float: left;
	display: block;
	color: #666;
}
.settings-inside input[type="text"] {
	padding: 10px;
	background: #fff;
	border: 1px solid #ebebeb;
	font-size: 16px;
	width: 280px;
	border-radius: 2px;
	outline: none;
	-webkit-transition:  all .1s linear;
	-moz-transition:  all .1s linear 0s;
}
.settings-inside input[type="text"]:hover {
	border: 1px solid #c9c9c9;
}
.settings-inside input[type="text"]:focus {
	border-bottom: 1px solid #da2828;
}
.settings-inside select {
	font-size: 16px;
	//margin-top: 15px;
}
.settings-inside input[type="checkbox"] {
	//margin-top: 15px;
	font-size: 14px;
	color: #666;
}

.button-primary, button.button-primary, a.button-primary {
	border-color:#298cba;
	font-weight:bold;
	color:#fff;
	background:#21759B;
	text-shadow:rgba(0,0,0,0.3) 0 -1px 0;
}
input.button-primary:active, button.button-primary:active, a.button-primary:active {
	background:#21759b;
	color:#eaf2fa;
}
input.button-primary:hover, button.button-primary:hover, a.button-primary:hover, a.button-primary:focus, a.button-primary:active {
	border-color:#13455b;
	color:#eaf2fa;
}