text:
/*
 * snmpksm.c
 *
 * This code implements the Kerberos Security Model (KSM) for SNMP.
 *
 * Security number - 2066432
 */

#include <net-snmp/net-snmp-config.h>

#include <sys/types.h>
#if HAVE_WINSOCK_H
#include <winsock.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if TIME_WITH_SYS_TIME
# ifdef WIN32
#  include <sys/timeb.h>
# else
#  include <sys/time.h>
# endif
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <errno.h>

#if HAVE_DMALLOC_H
#include <dmalloc.h>
#endif

#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
#ifndef NETSNMP_USE_KERBEROS_MIT
#define OLD_HEIMDAL
#endif 				/* ! NETSNMP_USE_KERBEROS_MIT */
#else
#define KRB5_DEPRECATED 1
#endif 				/* NETSNMP_USE_KERBEROS_HEIMDAL */

#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
#define oid heimdal_oid_renamed
#endif				/* NETSNMP_USE_KERBEROS_HEIMDAL */
#include <krb5.h>
#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
#undef oid
#endif				/* NETSNMP_USE_KERBEROS_HEIMDAL */

#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
#define CHECKSUM_TYPE(x)	(x)->cksumtype
#define CHECKSUM_CONTENTS(x)	(x)->checksum.data
#define CHECKSUM_LENGTH(x)	(x)->checksum.length
#define TICKET_CLIENT(x)	(x)->client
#else				/* NETSNMP_USE_KERBEROS_HEIMDAL */
#define CHECKSUM_TYPE(x)	(x)->checksum_type
#define CHECKSUM_CONTENTS(x)	(x)->contents
#define CHECKSUM_LENGTH(x)	(x)->length
#define TICKET_CLIENT(x)	(x)->enc_part2->client
#endif				/* NETSNMP_USE_KERBEROS_HEIMDAL */

#include <net-snmp/output_api.h>
#include <net-snmp/config_api.h>
#include <net-snmp/utilities.h>

#include <net-snmp/library/asn1.h>
#include <net-snmp/library/snmp_api.h>
#include <net-snmp/library/callback.h>
#include <net-snmp/library/keytools.h>
#include <net-snmp/library/snmpv3.h>
#include <net-snmp/library/lcd_time.h>
#include <net-snmp/library/scapi.h>
#include <net-snmp/library/callback.h>
#include <net-snmp/library/snmp_secmod.h>
#include <net-snmp/library/snmpksm.h>

static krb5_context kcontext = NULL;
static krb5_rcache rcache = NULL;
static krb5_keytab keytab = NULL;
static int keytab_setup = 0;
static char *service_name = NULL;
static char service_host[] = "host";
static u_char null_id[] = {0};

static int      ksm_session_init(netsnmp_session *);
static void     ksm_free_state_ref(void *);
static int      ksm_free_pdu(netsnmp_pdu *);
static int      ksm_clone_pdu(netsnmp_pdu *, netsnmp_pdu *);

static int      ksm_insert_cache(long, krb5_auth_context, u_char *,
                                 size_t);
static void     ksm_decrement_ref_count(long);
static void     ksm_increment_ref_count(long);
static struct ksm_cache_entry *ksm_get_cache(long);

#define HASHSIZE	64

/*
 * Our information stored for the response PDU.
 */

struct ksm_secStateRef {
    krb5_auth_context auth_context;
    krb5_cksumtype  cksumtype;
};

/*
 * A KSM outgoing pdu cache entry
 */

struct ksm_cache_entry {
    long            msgid;
    int             refcount;
    krb5_auth_context auth_context;
    u_char         *secName;
    size_t          secNameLen;
    struct ksm_cache_entry *next;
};

/*
 * Poor man's hash table
 */

static struct ksm_cache_entry *ksm_hash_table[HASHSIZE];

/*
 * Stuff to deal with config values
 * Note the conditionals that wrap these--i don't know if these are
 * needed, since i don't know how library initialization and callbacks
 * and stuff work
 */

static int
init_snmpksm_post_config(int majorid, int minorid, void *serverarg,
			 void *clientarg)
{

    if (kcontext == NULL) {
	/* not reached, i'd imagine */
        return SNMPERR_KRB5;
    }

    if (service_name == NULL) {
	/* always reached, i'd imagine */
	char *c = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
					NETSNMP_DS_LIB_KSM_SERVICE_NAME);
	if (c != NULL) {
		service_name = c;
	}
	else {
		service_name = service_host;
	}
    }

    if (keytab_setup == 0) {
	/* always reached, i'd imagine */
	char *c = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
					NETSNMP_DS_LIB_KSM_KEYTAB);
	if (c) {
	    krb5_error_code retval;
	    DEBUGMSGTL(("ksm", "Using keytab %s\n", c));
	    retval = krb5_kt_resolve(kcontext, c, &keytab);
	    if (retval) {
		DEBUGMSGTL(("ksm", "krb5_kt_resolve(\"%s\") failed. KSM "
			    "config callback failing\n", error_message(retval)));
		return SNMPERR_KRB5;
	    }
	}
	else {
	    DEBUGMSGTL(("ksm", "Using default keytab\n"));
	}
	keytab_setup = 1;
    }

    return SNMPERR_SUCCESS;
}

/*
 * Initialize all of the state required for Kerberos (right now, just call
 * krb5_init_context).
 */

void
init_ksm(void)
{
    krb5_error_code retval;
    struct snmp_secmod_def *def;
    int             i;

    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defKSMKeytab",
                               NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_KSM_KEYTAB);
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defKSMServiceName",
                               NETSNMP_DS_LIBRARY_ID,
			       NETSNMP_DS_LIB_KSM_SERVICE_NAME);
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
			   SNMP_CALLBACK_POST_READ_CONFIG,
			   init_snmpksm_post_config, NULL);

    if (kcontext == NULL) {
        retval = krb5_init_context(&kcontext);

        if (retval) {
            DEBUGMSGTL(("ksm", "krb5_init_context failed (%s), not "
                        "registering KSM\n", error_message(retval)));
            return;
        }
    }

    for (i = 0; i < HASHSIZE; i++)
        ksm_hash_table[i] = NULL;

    def = SNMP_MALLOC_STRUCT(snmp_secmod_def);

    if (!def) {
        DEBUGMSGTL(("ksm", "Unable to malloc snmp_secmod struct, not "
                    "registering KSM\n"));
        return;
    }

    def->encode_reverse = ksm_rgenerate_out_msg;
    def->decode = ksm_process_in_msg;
    def->session_open = ksm_session_init;
    def->pdu_free_state_ref = ksm_free_state_ref;
    def->pdu_free = ksm_free_pdu;
    def->pdu_clone = ksm_clone_pdu;

    register_sec_mod(NETSNMP_KSM_SECURITY_MODEL, "ksm", def);
}

/*
 * These routines implement a simple cache for information we need to
 * process responses.  When we send out a request, it contains an AP_REQ;
 * we get back an AP_REP, and we need the authorization context from the
 * AP_REQ to decrypt the AP_REP.  But because right now there's nothing
 * that gets preserved across calls to rgenerate_out_msg to process_in_msg,
 * we cache these internally based on the message ID (we also cache the
 * passed-in security name, for reasons that are mostly stupid).
 */

static int
ksm_insert_cache(long msgid, krb5_auth_context auth_context,
                 u_char * secName, size_t secNameLen)
{
    struct ksm_cache_entry *entry;
    int             bucket;

    entry = SNMP_MALLOC_STRUCT(ksm_cache_entry);
    if (!entry)
        return SNMPERR_MALLOC;

    entry->msgid = msgid;
    entry->auth_context = auth_context;
    entry->refcount = 1;
    entry->secName = netsnmp_memdup(secName, secNameLen);
    if (secName && !entry->secName) {
        free(entry);
        return SNMPERR_GENERR;
    }

    entry->secNameLen = secNameLen;

    bucket = msgid % HASHSIZE;

    entry->next = ksm_hash_table[bucket];
    ksm_hash_table[bucket] = entry;

    return SNMPERR_SUCCESS;
}

static struct ksm_cache_entry *
ksm_get_cache(long msgid)
{
    struct ksm_cache_entry *entry;
    int             bucket;

    bucket = msgid % HASHSIZE;

    for (entry = ksm_hash_table[bucket]; entry != NULL;
         entry = entry->next)
        if (entry->msgid == msgid)
            return entry;

    return NULL;
}

static void
ksm_decrement_ref_count(long msgid)
{
    struct ksm_cache_entry *entry, *entry1;
    int             bucket;

    bucket = msgid % HASHSIZE;

    if (ksm_hash_table[bucket] && ksm_hash_table[bucket]->msgid == msgid) {
        entry = ksm_hash_table[bucket];

        /*
         * If the reference count is zero, then free it
         */

        if (--entry->refcount <= 0) {
            DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n", msgid));
            krb5_auth_con_free(kcontext, entry->auth_context);
            free(entry->secName);
            ksm_hash_table[bucket] = entry->next;
            free(entry);
        }

        return;

    } else if (ksm_hash_table[bucket])
        for (entry1 = ksm_hash_table[bucket], entry = entry1->next;
             entry != NULL; entry1 = entry, entry = entry->next)
            if (entry->msgid == msgid) {

                if (--entry->refcount <= 0) {
                    DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n",
                                msgid));
                    krb5_auth_con_free(kcontext, entry->auth_context);
                    free(entry->secName);
                    entry1->next = entry->next;
                    free(entry);
                }

                return;
            }

    DEBUGMSGTL(("ksm",
                "KSM: Unable to decrement cache entry for msgid %ld.\n",
                msgid));
}

static void
ksm_increment_ref_count(long msgid)
{
    struct ksm_cache_entry *entry = ksm_get_cache(msgid);

    if (!entry) {
        DEBUGMSGTL(("ksm", "Unable to find cache entry for msgid %ld "
                    "for increment\n", msgid));
        return;
    }

    entry->refcount++;
}

/*
 * Initialize specific session information (right now, just set up things to
 * not do an engineID probe)
 */

static int
ksm_session_init(netsnmp_session * sess)
{
    DEBUGMSGTL(("ksm",
                "KSM: Reached our session initialization callback\n"));

    sess->flags |= SNMP_FLAGS_DONT_PROBE;

    return SNMPERR_SUCCESS;
}

/*
 * Free our state information (this is only done on the agent side)
 */

static void
ksm_free_state_ref(void *ptr)
{
    struct ksm_secStateRef *ref = (struct ksm_secStateRef *) ptr;

    DEBUGMSGTL(("ksm", "KSM: Freeing state reference\n"));

    krb5_auth_con_free(kcontext, ref->auth_context);

    free(ref);
}

/*
 * This is called when the PDU is freed; this will decrement reference counts
 * for entries in our state cache.
 */

static int
ksm_free_pdu(netsnmp_pdu *pdu)
{
    ksm_decrement_ref_count(pdu->msgid);

    DEBUGMSGTL(("ksm", "Decrementing cache entry for PDU msgid %ld\n",
                pdu->msgid));

    return SNMPERR_SUCCESS;
}

/*
 * This is called when a PDU is cloned (to increase reference counts)
 */

static int
ksm_clone_pdu(netsnmp_pdu *pdu, netsnmp_pdu *pdu2)
{
    ksm_increment_ref_count(pdu->msgid);

    DEBUGMSGTL(("ksm", "Incrementing cache entry for PDU msgid %ld\n",
                pdu->msgid));

    return SNMPERR_SUCCESS;
}

/****************************************************************************
 *
 * ksm_generate_out_msg
 *
 * Parameters:
 *	(See list below...)
 *
 * Returns:
 *	SNMPERR_GENERIC                        On success.
 *	SNMPERR_KRB5
 *	... and others
 *
 *
 * Generate an outgoing message.
 *
 ****************************************************************************/

int
ksm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms)
{
    krb5_auth_context auth_context = NULL;
    krb5_error_code retcode;
    krb5_ccache     cc = NULL;
    int             retval = SNMPERR_SUCCESS;
    krb5_data       outdata, ivector;
    krb5_keyblock  *subkey = NULL;
#ifdef NETSNMP_USE_KERBEROS_MIT
    krb5_data       input;
    krb5_enc_data   output;
    unsigned int    numcksumtypes;
    krb5_cksumtype  *cksumtype_array;
#elif defined OLD_HEIMDAL	/* NETSNMP_USE_KERBEROS_MIT */
    krb5_crypto heim_crypto = NULL;
#else                           /* NETSNMP_USE_KERBEROS_MIT */
    krb5_encrypt_block eblock;
#endif                          /* NETSNMP_USE_KERBEROS_MIT */
    size_t          blocksize, encrypted_length;
    unsigned char  *encrypted_data = NULL;
    long            zero = 0, tmp;
    int             i;
    u_char         *cksum_pointer;
    krb5_cksumtype  cksumtype;
    krb5_checksum   pdu_checksum;
    u_char         **wholeMsg = parms->wholeMsg;
    size_t	   *offset = parms->wholeMsgOffset, seq_offset;
    struct ksm_secStateRef *ksm_state = (struct ksm_secStateRef *)
        parms->secStateRef;
#ifdef OLD_HEIMDAL
    krb5_data encrypted_scoped_pdu;
#endif				/* OLD_HEIMDAL */
    int rc;
    char *colon = NULL;

    DEBUGMSGTL(("ksm", "Starting KSM processing\n"));

    outdata.length = 0;
    outdata.data = NULL;
    ivector.length = 0;
    ivector.data = NULL;
    CHECKSUM_CONTENTS(&pdu_checksum) = NULL;

    if (!ksm_state) {
        /*
         * If we've got a port number as part of the "peername", then
         * suppress this (temporarily) while we build the credential info.
         *   XXX - what about "udp:host" style addresses?
         */
        colon = strrchr(parms->session->peername, ':');
        if (colon != NULL) {
            *colon='\0';
        }

        /*
         * If we don't have a ksm_state, then we're a request.  Get a
         * credential cache and build a ap_req.
         */
        retcode = krb5_cc_default(kcontext, &cc);

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM: krb5_cc_default failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

        DEBUGMSGTL(("ksm", "KSM: Set credential cache successfully\n"));

        /*
         * This seems odd, since we don't need this until later (or earlier,
         * depending on how you look at it), but because the most likely
         * errors are Kerberos at this point, I'll get this now to save
         * time not encoding the rest of the packet.
         *
         * Also, we need the subkey to encrypt the PDU (if required).
         */

        retcode =
            krb5_mk_req(kcontext, &auth_context,
                        AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
                        service_name, parms->session->peername, NULL,
                        cc, &outdata);

        if (colon != NULL)
            *colon=':';

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM: krb5_mk_req failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

	DEBUGMSGTL(("ksm", "KSM: ticket retrieved successfully for \"%s/%s\" "
		    "(may not be actual ticket sname)\n", service_name,
		    parms->session->peername));

    } else {

        /*
         * Grab the auth_context from our security state reference
         */

        auth_context = ksm_state->auth_context;

        /*
         * Bundle up an AP_REP.  Note that we do this only when we
         * have a security state reference (which means we're in an agent
         * and we're sending a response).
         */

        DEBUGMSGTL(("ksm", "KSM: Starting reply processing.\n"));

        retcode = krb5_mk_rep(kcontext, auth_context, &outdata);

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM: krb5_mk_rep failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

        DEBUGMSGTL(("ksm", "KSM: Finished with krb5_mk_rep()\n"));
    }

    /*
     * If we have to encrypt the PDU, do that now
     */

    if (parms->secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {

        DEBUGMSGTL(("ksm", "KSM: Starting PDU encryption.\n"));

        /*
         * It's weird -
         *
         * If we're on the manager, it's a local subkey (because that's in
         * our AP_REQ)
         *
         * If we're on the agent, it's a remote subkey (because that comes
         * FROM the received AP_REQ).
         */

        if (ksm_state)
            retcode = krb5_auth_con_getremotesubkey(kcontext, auth_context,
                                                    &subkey);
        else
            retcode = krb5_auth_con_getlocalsubkey(kcontext, auth_context,
                                                   &subkey);

        if (retcode) {
            DEBUGMSGTL(("ksm",
                        "KSM: krb5_auth_con_getlocalsubkey failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

        /*
         * Note that here we need to handle different things between the
         * old and new crypto APIs.  First, we need to get the final encrypted
         * length of the PDU.
         */

#ifdef NETSNMP_USE_KERBEROS_MIT
        retcode = krb5_c_encrypt_length(kcontext, subkey->enctype,
                                        parms->scopedPduLen,
                                        &encrypted_length);

        if (retcode) {
            DEBUGMSGTL(("ksm",
                        "Encryption length calculation failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
#elif defined OLD_HEIMDAL
	retcode = krb5_crypto_init(kcontext, subkey, 0, &heim_crypto);
        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_crypto_init failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
	encrypted_length = krb5_get_wrapped_length(kcontext, heim_crypto,
						   parms->scopedPduLen);
#else                           /* NETSNMP_USE_KERBEROS_MIT */

        krb5_use_enctype(kcontext, &eblock, subkey->enctype);
        retcode = krb5_process_key(kcontext, &eblock, subkey);

        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_process_key failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

        encrypted_length = krb5_encrypt_size(parms->scopedPduLen,
                                             eblock.crypto_entry);
#endif                          /* NETSNMP_USE_KERBEROS_MIT */

#ifndef OLD_HEIMDAL /* since heimdal allocs the space for us */
        encrypted_data = malloc(encrypted_length);

        if (!encrypted_data) {
            DEBUGMSGTL(("ksm",
                        "KSM: Unable to malloc %d bytes for encrypt "
                        "buffer: %s\n", (int)parms->scopedPduLen,
                        strerror(errno)));
            retval = SNMPERR_MALLOC;
#ifndef NETSNMP_USE_KERBEROS_MIT
            krb5_finish_key(kcontext, &eblock);
#endif                          /* ! NETSNMP_USE_KERBEROS_MIT */

            goto error;
        }
#endif /* ! OLD_HEIMDAL */

        /*
         * We need to set up a blank initialization vector for the encryption.
         * Use a block of all zero's (which is dependent on the block size
         * of the encryption method).
         */

#ifdef NETSNMP_USE_KERBEROS_MIT

        retcode = krb5_c_block_size(kcontext, subkey->enctype, &blocksize);

        if (retcode) {
            DEBUGMSGTL(("ksm",
                        "Unable to determine crypto block size: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
#elif defined (OLD_HEIMDAL)	/* NETSNMP_USE_KERBEROS_MIT */
#else                           /* NETSNMP_USE_KERBEROS_MIT */

        blocksize =
            krb5_enctype_array[subkey->enctype]->system->block_length;

#endif                          /* NETSNMP_USE_KERBEROS_MIT */

#ifndef OLD_HEIMDAL	/* since allocs the space for us */
        ivector.data = malloc(blocksize);

        if (!ivector.data) {
            DEBUGMSGTL(("ksm", "Unable to allocate %d bytes for ivector\n",
                        (int)blocksize));
            retval = SNMPERR_MALLOC;
            goto error;
        }

        ivector.length = blocksize;
        memset(ivector.data, 0, blocksize);
#endif /* OLD_HEIMDAL */

        /*
         * Finally!  Do the encryption!
         */

#ifdef NETSNMP_USE_KERBEROS_MIT

        input.data = (char *) parms->scopedPdu;
        input.length = parms->scopedPduLen;
        output.ciphertext.data = (char *) encrypted_data;
        output.ciphertext.length = encrypted_length;

        retcode =
            krb5_c_encrypt(kcontext, subkey, KSM_KEY_USAGE_ENCRYPTION,
                           &ivector, &input, &output);

#elif defined OLD_HEIMDAL /* NETSNMP_USE_KERBEROS_MIT */

	krb5_data_zero(&encrypted_scoped_pdu);
	retcode = krb5_encrypt(kcontext, heim_crypto, KSM_KEY_USAGE_ENCRYPTION,
			       parms->scopedPdu, parms->scopedPduLen,
			       &encrypted_scoped_pdu);
	if (retcode == 0) {
		encrypted_length = encrypted_scoped_pdu.length;
		encrypted_data = encrypted_scoped_pdu.data;
		krb5_data_zero(&encrypted_scoped_pdu);
	}
#else                           /* NETSNMP_USE_KERBEROS_MIT */

        retcode = krb5_encrypt(kcontext, (krb5_pointer) parms->scopedPdu,
                               (krb5_pointer) encrypted_data,
                               parms->scopedPduLen, &eblock, ivector.data);

        krb5_finish_key(kcontext, &eblock);

#endif                          /* NETSNMP_USE_KERBEROS_MIT */

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM: krb5_encrypt failed: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            snmp_set_detail(error_message(retcode));
            goto error;
        }

	*offset = 0;

        rc = asn_realloc_rbuild_string(wholeMsg, parms->wholeMsgLen,
                                             offset, 1,
                                             (u_char) (ASN_UNIVERSAL |
                                                       ASN_PRIMITIVE |
                                                       ASN_OCTET_STR),
                                             encrypted_data,
                                             encrypted_length);

        if (rc == 0) {
            DEBUGMSGTL(("ksm", "Building encrypted payload failed.\n"));
            retval = SNMPERR_TOO_LONG;
            goto error;
        }

        DEBUGMSGTL(("ksm", "KSM: Encryption complete.\n"));

    } else {
        /*
         * Plaintext PDU (not encrypted)
         */

        if (*parms->wholeMsgLen < parms->scopedPduLen) {
            DEBUGMSGTL(("ksm", "Not enough room for plaintext PDU.\n"));
            retval = SNMPERR_TOO_LONG;
            goto error;
        }
    }

    /*
     * Start encoding the msgSecurityParameters
     *
     * For now, use 0 for the response hint
     */

    DEBUGMSGTL(("ksm", "KSM: scopedPdu added to payload\n"));

    seq_offset = *offset;

    rc = asn_realloc_rbuild_int(wholeMsg, parms->wholeMsgLen,
                                      offset, 1,
                                      (u_char) (ASN_UNIVERSAL |
                                                ASN_PRIMITIVE |
                                                ASN_INTEGER),
                                      (long *) &zero, sizeof(zero));

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    rc = asn_realloc_rbuild_string(wholeMsg, parms->wholeMsgLen,
                                         offset, 1,
                                         (u_char) (ASN_UNIVERSAL |
                                                   ASN_PRIMITIVE |
                                                   ASN_OCTET_STR),
                                         (u_char *) outdata.data,
                                         outdata.length);

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building ksm AP_REQ failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    /*
     * If we didn't encrypt the packet, we haven't yet got the subkey.
     * Get that now.
     */

    if (!subkey) {
        if (ksm_state)
            retcode = krb5_auth_con_getremotesubkey(kcontext, auth_context,
                                                    &subkey);
        else
            retcode = krb5_auth_con_getlocalsubkey(kcontext, auth_context,
                                                   &subkey);
        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_auth_con_getlocalsubkey failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
#ifdef OLD_HEIMDAL
	 retcode = krb5_crypto_init(kcontext, subkey, 0, &heim_crypto);
        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_crypto_init failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
#endif					/* OLD_HEIMDAL */
    }

    /*
     * Now, we need to pick the "right" checksum algorithm.  For old
     * crypto, just pick CKSUMTYPE_RSA_MD5_DES; for new crypto, pick
     * one of the "approved" ones.
     */

#ifdef NETSNMP_USE_KERBEROS_MIT
    retcode = krb5_c_keyed_checksum_types(kcontext, subkey->enctype,
                                          &numcksumtypes, &cksumtype_array);

    if (retcode) {
	DEBUGMSGTL(("ksm", "Unable to find appropriate keyed checksum: %s\n",
		    error_message(retcode)));
	snmp_set_detail(error_message(retcode));
        retval = SNMPERR_KRB5;
        goto error;
    }

    if (numcksumtypes <= 0) {
	DEBUGMSGTL(("ksm", "We received a list of zero cksumtypes for this "
		    "enctype (%d)\n", subkey->enctype));
	snmp_set_detail("No valid checksum type for this encryption type");
	retval = SNMPERR_KRB5;
	goto error;
    }

    /*
     * It's not clear to me from the API which checksum you're supposed
     * to support, so I'm taking a guess at the first one
     */

    cksumtype = cksumtype_array[0];

    krb5_free_cksumtypes(kcontext, cksumtype_array);

    DEBUGMSGTL(("ksm", "KSM: Choosing checksum type of %d (subkey type "
		"of %d)\n", cksumtype, subkey->enctype));

    retcode = krb5_c_checksum_length(kcontext, cksumtype, &blocksize);

    if (retcode) {
        DEBUGMSGTL(("ksm", "Unable to determine checksum length: %s\n",
                    error_message(retcode)));
        snmp_set_detail(error_message(retcode));
        retval = SNMPERR_KRB5;
        goto error;
    }

    CHECKSUM_LENGTH(&pdu_checksum) = blocksize;

#else /* NETSNMP_USE_KERBEROS_MIT */
    if (ksm_state)
        cksumtype = ksm_state->cksumtype;
    else
#ifdef OLD_HEIMDAL
    {
	    /* no way to tell what kind of checksum to use without trying */
	    retval = krb5_create_checksum(kcontext, heim_crypto,
					  KSM_KEY_USAGE_CHECKSUM, 0,
					  parms->scopedPdu, parms->scopedPduLen,
					  &pdu_checksum);
	    if (retval) {
		    DEBUGMSGTL(("ksm", "Unable to create a checksum: %s\n",
				error_message(retval)));
		    snmp_set_detail(error_message(retcode));
		    retval = SNMPERR_KRB5;
		    goto error;
	    }
	    cksumtype = CHECKSUM_TYPE(&pdu_checksum);
    }
#else					/* OLD_HEIMDAL */
	cksumtype = CKSUMTYPE_RSA_MD5_DES;
#endif					/* OLD_HEIMDAL */

#ifdef OLD_HEIMDAL
	if (!krb5_checksum_is_keyed(kcontext, cksumtype)) {
#else 				/* OLD_HEIMDAL */
    if (!is_keyed_cksum(cksumtype)) {
#endif 				/* OLD_HEIMDAL */
        DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n",
                    cksumtype));
        snmp_set_detail("Checksum is not a keyed checksum");
        retval = SNMPERR_KRB5;
        goto error;
    }

#ifdef OLD_HEIMDAL
    if (!krb5_checksum_is_collision_proof(kcontext, cksumtype)) {
#else 				/* OLD_HEIMDAL */
    if (!is_coll_proof_cksum(cksumtype)) {
#endif 				/* OLD_HEIMDAL */
        DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof "
                    "checksum\n", cksumtype));
        snmp_set_detail("Checksum is not a collision-proof checksum");
        retval = SNMPERR_KRB5;
        goto error;
    }

#ifdef OLD_HEIMDAL
    if (CHECKSUM_CONTENTS(&pdu_checksum) != NULL ) {
	/* we did the bogus checksum--don't need to ask for the size again
	 * or initialize cksumtype; just free the bits */
	free(CHECKSUM_CONTENTS(&pdu_checksum));
	CHECKSUM_CONTENTS(&pdu_checksum) = NULL;
    }
    else {
	retval = krb5_checksumsize(kcontext, cksumtype,
				   &CHECKSUM_LENGTH(&pdu_checksum));
	if (retval) {
	    DEBUGMSGTL(("ksm", "Unable to determine checksum length: %s\n",
			error_message(retval)));
	    snmp_set_detail(error_message(retcode));
	    retval = SNMPERR_KRB5;
	    goto error;
	}
#else			/* OLD_HEIMDAL */
    CHECKSUM_LENGTH(&pdu_checksum) = krb5_checksum_size(kcontext, cksumtype);
#endif			/* OLD_HEIMDAL */
    CHECKSUM_TYPE(&pdu_checksum) = cksumtype;
#ifdef OLD_HEIMDAL
    }
#endif			/* OLD_HEIMDAL */

#endif /* NETSNMP_USE_KERBEROS_MIT */

    /*
     * Note that here, we're just leaving blank space for the checksum;
     * we remember where that is, and we'll fill it in later.
     */

    *offset += CHECKSUM_LENGTH(&pdu_checksum);
    memset(*wholeMsg + *parms->wholeMsgLen - *offset, 0, CHECKSUM_LENGTH(&pdu_checksum));

    cksum_pointer = *wholeMsg + *parms->wholeMsgLen - *offset;

    rc = asn_realloc_rbuild_header(wholeMsg, parms->wholeMsgLen,
                                         parms->wholeMsgOffset, 1,
                                         (u_char) (ASN_UNIVERSAL |
                                                   ASN_PRIMITIVE |
                                                   ASN_OCTET_STR),
                                         CHECKSUM_LENGTH(&pdu_checksum));

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    tmp = cksumtype;
    rc = asn_realloc_rbuild_int(wholeMsg, parms->wholeMsgLen,
                                      parms->wholeMsgOffset, 1,
                                      (u_char) (ASN_UNIVERSAL |
                                                ASN_PRIMITIVE |
                                                ASN_INTEGER),
                                      &tmp, sizeof(tmp));

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    rc = asn_realloc_rbuild_sequence(wholeMsg, parms->wholeMsgLen,
                                           parms->wholeMsgOffset, 1,
                                           (u_char) (ASN_SEQUENCE |
                                                     ASN_CONSTRUCTOR),
                                           *offset - seq_offset);

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    rc = asn_realloc_rbuild_header(wholeMsg, parms->wholeMsgLen,
                                         parms->wholeMsgOffset, 1,
                                         (u_char) (ASN_UNIVERSAL |
                                                   ASN_PRIMITIVE |
                                                   ASN_OCTET_STR),
                                         *offset - seq_offset);

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    DEBUGMSGTL(("ksm", "KSM: Security parameter encoding completed\n"));

    /*
     * We're done with the KSM security parameters - now we do the global
     * header and wrap up the whole PDU.
     */

    if (*parms->wholeMsgLen < parms->globalDataLen) {
        DEBUGMSGTL(("ksm", "Building global data failed.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    *offset += parms->globalDataLen;
    memcpy(*wholeMsg + *parms->wholeMsgLen - *offset,
	   parms->globalData, parms->globalDataLen);

    rc = asn_realloc_rbuild_sequence(wholeMsg, parms->wholeMsgLen,
                                           offset, 1,
                                           (u_char) (ASN_SEQUENCE |
                                                     ASN_CONSTRUCTOR),
                                           *offset);

    if (rc == 0) {
        DEBUGMSGTL(("ksm", "Building master packet sequence.\n"));
        retval = SNMPERR_TOO_LONG;
        goto error;
    }

    DEBUGMSGTL(("ksm", "KSM: PDU master packet encoding complete.\n"));

    /*
     * Now we need to checksum the entire PDU (since it's built).
     */

#ifndef OLD_HEIMDAL /* since heimdal allocs the mem for us */
    CHECKSUM_CONTENTS(&pdu_checksum) = malloc(CHECKSUM_LENGTH(&pdu_checksum));

    if (!CHECKSUM_CONTENTS(&pdu_checksum)) {
        DEBUGMSGTL(("ksm", "Unable to malloc %d bytes for checksum\n",
                    CHECKSUM_LENGTH(&pdu_checksum)));
        retval = SNMPERR_MALLOC;
        goto error;
    }
#endif					/* ! OLD_HEIMDAL */
#ifdef NETSNMP_USE_KERBEROS_MIT

    input.data = (char *) (*wholeMsg + *parms->wholeMsgLen - *offset);
    input.length = *offset;
        retcode = krb5_c_make_checksum(kcontext, cksumtype, subkey,
                                       KSM_KEY_USAGE_CHECKSUM, &input,
                                       &pdu_checksum);

#elif defined(OLD_HEIMDAL)	/* NETSNMP_USE_KERBEROS_MIT */

	retcode = krb5_create_checksum(kcontext, heim_crypto,
				       KSM_KEY_USAGE_CHECKSUM, cksumtype,
				       *wholeMsg + *parms->wholeMsgLen
				       - *offset, *offset, &pdu_checksum);
#else                           /* NETSNMP_USE_KERBEROS_MIT */

    retcode = krb5_calculate_checksum(kcontext, cksumtype, *wholeMsg +
				      *parms->wholeMsgLen - *offset,
                                      *offset,
                                      (krb5_pointer) subkey->contents,
                                      subkey->length, &pdu_checksum);

#endif                          /* NETSNMP_USE_KERBEROS_MIT */

    if (retcode) {
        DEBUGMSGTL(("ksm", "Calculate checksum failed: %s\n",
                    error_message(retcode)));
        retval = SNMPERR_KRB5;
        snmp_set_detail(error_message(retcode));
        goto error;
    }

    DEBUGMSGTL(("ksm", "KSM: Checksum calculation complete.\n"));

    memcpy(cksum_pointer, CHECKSUM_CONTENTS(&pdu_checksum), CHECKSUM_LENGTH(&pdu_checksum));

    DEBUGMSGTL(("ksm", "KSM: Writing checksum of %d bytes at offset %d\n",
                (int)CHECKSUM_LENGTH(&pdu_checksum),
		(int)(cksum_pointer - (*wholeMsg + 1))));

    DEBUGMSGTL(("ksm", "KSM: Checksum:"));

    for (i = 0; i < CHECKSUM_LENGTH(&pdu_checksum); i++)
        DEBUGMSG(("ksm", " %02x",
                  (unsigned int) ((unsigned char *)CHECKSUM_CONTENTS(&pdu_checksum))[i]));

    DEBUGMSG(("ksm", "\n"));

    /*
     * If we're _not_ called as part of a response (null ksm_state),
     * then save the auth_context for later using our cache routines.
     */

    if (!ksm_state) {
        if ((retval = ksm_insert_cache(parms->pdu->msgid, auth_context,
                                       (u_char *) parms->secName,
                                       parms->secNameLen)) !=
            SNMPERR_SUCCESS)
            goto error;
        auth_context = NULL;
    }

    DEBUGMSGTL(("ksm", "KSM processing complete!\n"));

  error:

    if (CHECKSUM_CONTENTS(&pdu_checksum))
#ifdef NETSNMP_USE_KERBEROS_MIT
        krb5_free_checksum_contents(kcontext, &pdu_checksum);
#else                           /* NETSNMP_USE_KERBEROS_MIT */
        free(CHECKSUM_CONTENTS(&pdu_checksum));
#endif                          /* NETSNMP_USE_KERBEROS_MIT */

    if (ivector.data)
        free(ivector.data);

    if (subkey)
        krb5_free_keyblock(kcontext, subkey);

#ifdef OLD_HEIMDAL /* OLD_HEIMDAL */
    if (heim_crypto)
	    krb5_crypto_destroy(kcontext, heim_crypto);
#endif /* OLD_HEIMDAL */

    if (encrypted_data)
        free(encrypted_data);

    if (cc)
        krb5_cc_close(kcontext, cc);

    if (auth_context && !ksm_state)
        krb5_auth_con_free(kcontext, auth_context);

    return retval;
}

/****************************************************************************
 *
 * ksm_process_in_msg
 *
 * Parameters:
 *	(See list below...)
 *
 * Returns:
 *	KSM_ERR_NO_ERROR                        On success.
 *	SNMPERR_KRB5
 *	KSM_ERR_GENERIC_ERROR
 *	KSM_ERR_UNSUPPORTED_SECURITY_LEVEL
 *
 *
 * Processes an incoming message.
 *
 ****************************************************************************/

int
ksm_process_in_msg(struct snmp_secmod_incoming_params *parms)
{
    long            temp;
    krb5_cksumtype  cksumtype;
    krb5_auth_context auth_context = NULL;
    krb5_error_code retcode;
    krb5_checksum   checksum;
    krb5_data       ap_req, ivector;
    krb5_flags      flags;
    krb5_keyblock  *subkey = NULL;
#ifdef NETSNMP_USE_KERBEROS_MIT
    krb5_data       input, output;
    krb5_boolean    valid;
    krb5_enc_data   in_crypt;
#elif defined OLD_HEIMDAL	/* NETSNMP_USE_KERBEROS_MIT */
    krb5_data output;
    krb5_crypto heim_crypto = NULL;
#else                           /* NETSNMP_USE_KERBEROS_MIT */
    krb5_encrypt_block eblock;
#endif                          /* NETSNMP_USE_KERBEROS_MIT */
    krb5_ticket    *ticket = NULL;
    int             retval = SNMPERR_SUCCESS, response = 0;
    size_t          length =
        parms->wholeMsgLen - (u_int) (parms->secParams - parms->wholeMsg);
    u_char         *current = parms->secParams, type;
    size_t          cksumlength, blocksize;
    long            hint;
    char           *cname;
    struct ksm_secStateRef *ksm_state;
    struct ksm_cache_entry *entry;

    DEBUGMSGTL(("ksm", "Processing has begun\n"));

    CHECKSUM_CONTENTS(&checksum) = NULL;
    ap_req.data = NULL;
    ivector.length = 0;
    ivector.data = NULL;

    /*
     * First, parse the security parameters (because we need the subkey inside
     * of the ticket to do anything
     */

    if ((current = asn_parse_sequence(current, &length, &type,
                                      (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                       ASN_OCTET_STR),
                                      "ksm first octet")) == NULL) {
        DEBUGMSGTL(("ksm", "Initial security paramter parsing failed\n"));

        retval = SNMPERR_ASN_PARSE_ERR;
        goto error;
    }

    if ((current = asn_parse_sequence(current, &length, &type,
                                      (ASN_SEQUENCE | ASN_CONSTRUCTOR),
                                      "ksm sequence")) == NULL) {
        DEBUGMSGTL(("ksm",
                    "Security parameter sequence parsing failed\n"));

        retval = SNMPERR_ASN_PARSE_ERR;
        goto error;
    }

    if ((current = asn_parse_int(current, &length, &type, &temp,
                                 sizeof(temp))) == NULL) {
        DEBUGMSGTL(("ksm", "Security parameter checksum type parsing"
                    "failed\n"));

        retval = SNMPERR_ASN_PARSE_ERR;
        goto error;
    }

    cksumtype = temp;

#ifdef NETSNMP_USE_KERBEROS_MIT
    if (!krb5_c_valid_cksumtype(cksumtype)) {
        DEBUGMSGTL(("ksm", "Invalid checksum type (%d)\n", cksumtype));

        retval = SNMPERR_KRB5;
        snmp_set_detail("Invalid checksum type");
        goto error;
    }

    if (!krb5_c_is_keyed_cksum(cksumtype)) {
        DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n",
                    cksumtype));
        snmp_set_detail("Checksum is not a keyed checksum");
        retval = SNMPERR_KRB5;
        goto error;
    }

    if (!krb5_c_is_coll_proof_cksum(cksumtype)) {
        DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof "
                    "checksum\n", cksumtype));
        snmp_set_detail("Checksum is not a collision-proof checksum");
        retval = SNMPERR_KRB5;
        goto error;
    }
#else /* ! NETSNMP_USE_KERBEROS_MIT */
#ifdef OLD_HEIMDAL
    /* kludge */
    if (krb5_checksumsize(kcontext, cksumtype, &cksumlength)) {
#else					/* OLD_HEIMDAL */
    if (!valid_cksumtype(cksumtype)) {
#endif					/* OLD_HEIMDAL */
        DEBUGMSGTL(("ksm", "Invalid checksum type (%d)\n", cksumtype));

        retval = SNMPERR_KRB5;
        snmp_set_detail("Invalid checksum type");
        goto error;
    }

#ifdef OLD_HEIMDAL
    if (!krb5_checksum_is_keyed(kcontext, cksumtype)) {
#else					/* OLD_HEIMDAL */
    if (!is_keyed_cksum(cksumtype)) {
#endif					/* OLD_HEIMDAL */
        DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n",
                    cksumtype));
        snmp_set_detail("Checksum is not a keyed checksum");
        retval = SNMPERR_KRB5;
        goto error;
    }

#ifdef OLD_HEIMDAL
    if (!krb5_checksum_is_collision_proof(kcontext, cksumtype)) {
#else					/* OLD_HEIMDAL */
    if (!is_coll_proof_cksum(cksumtype)) {
#endif					/* OLD_HEIMDAL */
        DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof "
                    "checksum\n", cksumtype));
        snmp_set_detail("Checksum is not a collision-proof checksum");
        retval = SNMPERR_KRB5;
        goto error;
    }
#endif /* NETSNMP_USE_KERBEROS_MIT */

    CHECKSUM_TYPE(&checksum) = cksumtype;

    cksumlength = length;

    if ((current = asn_parse_sequence(current, &cksumlength, &type,
                                      (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                       ASN_OCTET_STR), "ksm checksum")) ==
        NULL) {
        DEBUGMSGTL(("ksm",
                    "Security parameter checksum parsing failed\n"));

        retval = SNMPERR_ASN_PARSE_ERR;
        goto error;
    }

    CHECKSUM_CONTENTS(&checksum) = malloc(cksumlength);
    if (!CHECKSUM_CONTENTS(&checksum)) {
        DEBUGMSGTL(("ksm", "Unable to malloc %d bytes for checksum.\n",
                    (int)cksumlength));
        retval = SNMPERR_MALLOC;
        goto error;
    }

    memcpy(CHECKSUM_CONTENTS(&checksum), current, cksumlength);

    CHECKSUM_LENGTH(&checksum) = cksumlength;
    CHECKSUM_TYPE(&checksum) = cksumtype;

    /*
     * Zero out the checksum so the validation works correctly
     */

    memset(current, 0, cksumlength);

    current += cksumlength;
    length = parms->wholeMsgLen - (u_int) (current - parms->wholeMsg);

    if ((current = asn_parse_sequence(current, &length, &type,
                                      (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                       ASN_OCTET_STR), "ksm ap_req")) ==
        NULL) {
        DEBUGMSGTL(("ksm", "KSM security parameter AP_REQ/REP parsing "
                    "failed\n"));

        retval = SNMPERR_ASN_PARSE_ERR;
        goto error;
    }

    ap_req.length = length;
    ap_req.data = malloc(length);
    if (!ap_req.data) {
        DEBUGMSGTL(("ksm",
                    "KSM unable to malloc %d bytes for AP_REQ/REP.\n",
                    (int)length));
        retval = SNMPERR_MALLOC;
        goto error;
    }

    memcpy(ap_req.data, current, length);

    current += length;
    length = parms->wholeMsgLen - (u_int) (current - parms->wholeMsg);

    if ((current = asn_parse_int(current, &length, &type, &hint,
                                 sizeof(hint))) == NULL) {
        DEBUGMSGTL(("ksm",
                    "KSM security parameter hint parsing failed\n"));

        retval = SNMPERR_ASN_PARSE_ERR;
        goto error;
    }

    /*
     * Okay!  We've got it all!  Now try decoding the damn ticket.
     *
     * But of course there's a WRINKLE!  We need to figure out if we're
     * processing a AP_REQ or an AP_REP.  How do we do that?  We're going
     * to cheat, and look at the first couple of bytes (which is what
     * the Kerberos library routines do anyway).
     *
     * If there are ever new Kerberos message formats, we'll need to fix
     * this here.
     *
     * If it's a _response_, then we need to get the auth_context
     * from our cache.
     */

    if (ap_req.length
#ifndef NETSNMP_USE_KERBEROS_HEIMDAL
        && (ap_req.data[0] == 0x6e || ap_req.data[0] == 0x4e)) {
#else				/* NETSNMP_USE_KERBEROS_HEIMDAL */
        && (((char *)ap_req.data)[0] == 0x6e || ((char *)ap_req.data)[0] == 0x4e)) {
#endif

        /*
         * We need to initalize the authorization context, and set the
         * replay cache in it (and initialize the replay cache if we
         * haven't already
         */

        retcode = krb5_auth_con_init(kcontext, &auth_context);

        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_auth_con_init failed: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            snmp_set_detail(error_message(retcode));
            goto error;
        }

        if (!rcache) {
            krb5_data       server;
            server.data = service_host;
            server.length = strlen(server.data);

            retcode = krb5_get_server_rcache(kcontext, &server, &rcache);

            if (retcode) {
                DEBUGMSGTL(("ksm", "krb5_get_server_rcache failed: %s\n",
                            error_message(retcode)));
                retval = SNMPERR_KRB5;
                snmp_set_detail(error_message(retcode));
                goto error;
            }
        }

        retcode = krb5_auth_con_setrcache(kcontext, auth_context, rcache);

        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_auth_con_setrcache failed: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            snmp_set_detail(error_message(retcode));
            goto error;
        }

        retcode = krb5_rd_req(kcontext, &auth_context, &ap_req, NULL,
                              keytab, &flags, &ticket);

        krb5_auth_con_setrcache(kcontext, auth_context, NULL);

        if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_rd_req() failed: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            snmp_set_detail(error_message(retcode));
            goto error;
        }

        retcode =
            krb5_unparse_name(kcontext, TICKET_CLIENT(ticket), &cname);

        if (retcode == 0) {
            DEBUGMSGTL(("ksm", "KSM authenticated principal name: %s\n",
                        cname));
            free(cname);
        }

        /*
         * Check to make sure AP_OPTS_MUTUAL_REQUIRED was set
         */

        if (!(flags & AP_OPTS_MUTUAL_REQUIRED)) {
            DEBUGMSGTL(("ksm",
                        "KSM MUTUAL_REQUIRED not set in request!\n"));
            retval = SNMPERR_KRB5;
            snmp_set_detail("MUTUAL_REQUIRED not set in message");
            goto error;
        }

        retcode =
            krb5_auth_con_getremotesubkey(kcontext, auth_context, &subkey);

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM remote subkey retrieval failed: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            snmp_set_detail(error_message(retcode));
            goto error;
        }

#ifndef NETSNMP_USE_KERBEROS_HEIMDAL
    } else if (ap_req.length && (ap_req.data[0] == 0x6f ||
                                 ap_req.data[0] == 0x4f)) {
#else				/* NETSNMP_USE_KERBEROS_HEIMDAL */
    } else if (ap_req.length && (((char *)ap_req.data)[0] == 0x6f ||
                                 ((char *)ap_req.data)[0] == 0x4f)) {
#endif				/* NETSNMP_USE_KERBEROS_HEIMDAL */
        /*
         * Looks like a response; let's see if we've got that auth_context
         * in our cache.
         */

        krb5_ap_rep_enc_part *repl = NULL;

        response = 1;

        entry = ksm_get_cache(parms->pdu->msgid);

        if (!entry) {
            DEBUGMSGTL(("ksm",
                        "KSM: Unable to find auth_context for PDU with "
                        "message ID of %ld\n", parms->pdu->msgid));
            retval = SNMPERR_KRB5;
            goto error;
        }

        auth_context = entry->auth_context;

        /*
         * In that case, let's call the rd_rep function
         */

        retcode = krb5_rd_rep(kcontext, auth_context, &ap_req, &repl);

        if (repl)
            krb5_free_ap_rep_enc_part(kcontext, repl);

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM: krb5_rd_rep() failed: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            goto error;
        }

        DEBUGMSGTL(("ksm", "KSM: krb5_rd_rep() decoded successfully.\n"));

        retcode =
            krb5_auth_con_getlocalsubkey(kcontext, auth_context, &subkey);

        if (retcode) {
            DEBUGMSGTL(("ksm", "Unable to retrieve local subkey: %s\n",
                        error_message(retcode)));
            retval = SNMPERR_KRB5;
            snmp_set_detail("Unable to retrieve local subkey");
            goto error;
        }

    } else {
#ifndef NETSNMP_USE_KERBEROS_HEIMDAL
        DEBUGMSGTL(("ksm", "Unknown Kerberos message type (%02x)\n",
                    ap_req.data[0]));
#else 				/* NETSNMP_USE_KERBEROS_HEIMDAL */
	 DEBUGMSGTL(("ksm", "Unknown Kerberos message type (%02x)\n",
                    ((char *)ap_req.data)[0]));
#endif
        retval = SNMPERR_KRB5;
        snmp_set_detail("Unknown Kerberos message type");
        goto error;
    }

#ifdef NETSNMP_USE_KERBEROS_MIT
    input.data = (char *) parms->wholeMsg;
    input.length = parms->wholeMsgLen;

    retcode =
        krb5_c_verify_checksum(kcontext, subkey, KSM_KEY_USAGE_CHECKSUM,
                               &input, &checksum, &valid);
#elif defined(OLD_HEIMDAL)	/* NETSNMP_USE_KERBEROS_MIT */
    retcode = krb5_crypto_init(kcontext, subkey, 0, &heim_crypto);
    if (retcode) {
            DEBUGMSGTL(("ksm", "krb5_crypto_init failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
    }
    retcode = krb5_verify_checksum(kcontext, heim_crypto,
				   KSM_KEY_USAGE_CHECKSUM, parms->wholeMsg,
				   parms->wholeMsgLen, &checksum);
#else                           /* NETSNMP_USE_KERBEROS_MIT */
    retcode = krb5_verify_checksum(kcontext, cksumtype, &checksum,
                                   parms->wholeMsg, parms->wholeMsgLen,
                                   (krb5_pointer) subkey->contents,
                                   subkey->length);
#endif                          /* NETSNMP_USE_KERBEROS_MIT */

    if (retcode) {
        DEBUGMSGTL(("ksm", "KSM checksum verification failed: %s\n",
                    error_message(retcode)));
        retval = SNMPERR_KRB5;
        snmp_set_detail(error_message(retcode));
        goto error;
    }

    /*
     * Don't ask me why they didn't simply return an error, but we have
     * to check to see if "valid" is false.
     */

#ifdef NETSNMP_USE_KERBEROS_MIT
    if (!valid) {
        DEBUGMSGTL(("ksm", "Computed checksum did not match supplied "
                    "checksum!\n"));
        retval = SNMPERR_KRB5;
        snmp_set_detail
            ("Computed checksum did not match supplied checksum");
        goto error;
    }
#endif                          /* NETSNMP_USE_KERBEROS_MIT */

    /*
     * Handle an encrypted PDU.  Note that it's an OCTET_STRING of the
     * output of whatever Kerberos cryptosystem you're using (defined by
     * the encryption type).  Note that this is NOT the EncryptedData
     * sequence - it's what goes in the "cipher" field of EncryptedData.
     */

    if (parms->secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {

        if ((current = asn_parse_sequence(current, &length, &type,
                                          (ASN_UNIVERSAL | ASN_PRIMITIVE |
                                           ASN_OCTET_STR), "ksm pdu")) ==
            NULL) {
            DEBUGMSGTL(("ksm", "KSM sPDU octet decoding failed\n"));
            retval = SNMPERR_ASN_PARSE_ERR;
            goto error;
        }

        /*
         * The PDU is now pointed at by "current", and the length is in
         * "length".
         */

        DEBUGMSGTL(("ksm", "KSM starting sPDU decode\n"));

        /*
         * We need to set up a blank initialization vector for the decryption.
         * Use a block of all zero's (which is dependent on the block size
         * of the encryption method).
         */

#ifdef NETSNMP_USE_KERBEROS_MIT

        retcode = krb5_c_block_size(kcontext, subkey->enctype, &blocksize);

        if (retcode) {
            DEBUGMSGTL(("ksm",
                        "Unable to determine crypto block size: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
#elif defined(OLD_HEIMDAL)	/* NETSNMP_USE_KERBEROS_MIT */
#else                           /* NETSNMP_USE_KERBEROS_MIT */

        blocksize =
            krb5_enctype_array[subkey->enctype]->system->block_length;

#endif                          /* NETSNMP_USE_KERBEROS_MIT */

#ifndef OLD_HEIMDAL
        ivector.data = malloc(blocksize);

        if (!ivector.data) {
            DEBUGMSGTL(("ksm", "Unable to allocate %d bytes for ivector\n",
                        (int)blocksize));
            retval = SNMPERR_MALLOC;
            goto error;
        }

        ivector.length = blocksize;
        memset(ivector.data, 0, blocksize);

#ifndef NETSNMP_USE_KERBEROS_MIT

        krb5_use_enctype(kcontext, &eblock, subkey->enctype);

        retcode = krb5_process_key(kcontext, &eblock, subkey);

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM key post-processing failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }
#endif                          /* !NETSNMP_USE_KERBEROS_MIT */

#endif /* ! OLD_HEIMDAL */

        if (length > *parms->scopedPduLen) {
            DEBUGMSGTL(("ksm", "KSM not enough room - have %d bytes to "
                        "decrypt but only %d bytes available\n", (int)length,
                        (int)*parms->scopedPduLen));
            retval = SNMPERR_TOO_LONG;
#ifndef NETSNMP_USE_KERBEROS_MIT
#ifndef OLD_HEIMDAL
            krb5_finish_key(kcontext, &eblock);
#endif                          /* ! OLD_HEIMDAL */
#endif                          /* ! NETSNMP_USE_KERBEROS_MIT */
            goto error;
        }
#ifdef NETSNMP_USE_KERBEROS_MIT
        in_crypt.ciphertext.data = (char *) current;
        in_crypt.ciphertext.length = length;
        in_crypt.enctype = subkey->enctype;
        output.data = (char *) *parms->scopedPdu;
        output.length = *parms->scopedPduLen;

        retcode =
            krb5_c_decrypt(kcontext, subkey, KSM_KEY_USAGE_ENCRYPTION,
                           &ivector, &in_crypt, &output);
#elif defined (OLD_HEIMDAL)	/* NETSNMP_USE_KERBEROS_MIT */
	retcode = krb5_decrypt(kcontext, heim_crypto, KSM_KEY_USAGE_ENCRYPTION,
			       current, length, &output);
	if (retcode == 0) {
		*parms->scopedPdu = (char *) output.data;
		*parms->scopedPduLen = output.length;
		krb5_data_zero(&output);
	}
#else                           /* NETSNMP_USE_KERBEROS_MIT */

        retcode = krb5_decrypt(kcontext, (krb5_pointer) current,
                               *parms->scopedPdu, length, &eblock,
                               ivector.data);

        krb5_finish_key(kcontext, &eblock);

#endif                          /* NETSNMP_USE_KERBEROS_MIT */

        if (retcode) {
            DEBUGMSGTL(("ksm", "Decryption failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

        *parms->scopedPduLen = length;

    } else {
        /*
         * Clear PDU
         */

        *parms->scopedPdu = current;
        *parms->scopedPduLen =
            parms->wholeMsgLen - (current - parms->wholeMsg);
    }

    /*
     * A HUGE GROSS HACK
     */

    *parms->maxSizeResponse = parms->maxMsgSize - 200;

    DEBUGMSGTL(("ksm", "KSM processing complete\n"));

    /*
     * Set the secName to the right value (a hack for now).  But that's
     * only used for when we're processing a request, not a response.
     */

    if (!response) {

        retcode = krb5_unparse_name(kcontext, TICKET_CLIENT(ticket),
                                    &cname);

        if (retcode) {
            DEBUGMSGTL(("ksm", "KSM krb5_unparse_name failed: %s\n",
                        error_message(retcode)));
            snmp_set_detail(error_message(retcode));
            retval = SNMPERR_KRB5;
            goto error;
        }

        if (strlen(cname) > *parms->secNameLen + 1) {
            DEBUGMSGTL(("ksm",
                        "KSM: Principal length (%d) is too long (%d)\n",
                        (int)strlen(cname), (int)*parms->secNameLen));
            retval = SNMPERR_TOO_LONG;
            free(cname);
            goto error;
        }

        strcpy(parms->secName, cname);
        *parms->secNameLen = strlen(cname);

        free(cname);

        /*
         * Also, if we're not a response, keep around our auth_context so we
         * can encode the reply message correctly
         */

        ksm_state = SNMP_MALLOC_STRUCT(ksm_secStateRef);

        if (!ksm_state) {
            DEBUGMSGTL(("ksm", "KSM unable to malloc memory for "
                        "ksm_secStateRef\n"));
            retval = SNMPERR_MALLOC;
            goto error;
        }

        ksm_state->auth_context = auth_context;
        auth_context = NULL;
        ksm_state->cksumtype = cksumtype;

        *parms->secStateRef = ksm_state;
    } else {

        /*
         * We _still_ have to set the secName in process_in_msg().  Do
         * that now with what we were passed in before (we cached it,
         * remember?)
         */

        memcpy(parms->secName, entry->secName, entry->secNameLen);
        *parms->secNameLen = entry->secNameLen;
    }

    /*
     * Just in case
     */

    parms->secEngineID = null_id;
    *parms->secEngineIDLen = 0;

    auth_context = NULL;        /* So we don't try to free it on success */

  error:
    if (retval == SNMPERR_ASN_PARSE_ERR &&
        snmp_increment_statistic(STAT_SNMPINASNPARSEERRS) == 0)
        DEBUGMSGTL(("ksm", "Failed to increment statistics.\n"));

    if (subkey)
        krb5_free_keyblock(kcontext, subkey);

#ifdef OLD_HEIMDAL /* OLD_HEIMDAL */
    if (heim_crypto)
	    krb5_crypto_destroy(kcontext, heim_crypto);
#endif /* OLD_HEIMDAL */

    if (CHECKSUM_CONTENTS(&checksum))
        free(CHECKSUM_CONTENTS(&checksum));

    if (ivector.data)
        free(ivector.data);

    if (ticket)
        krb5_free_ticket(kcontext, ticket);

    if (!response && auth_context)
        krb5_auth_con_free(kcontext, auth_context);

    if (ap_req.data)
        free(ap_req.data);

    return retval;
}


text:
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'uk_address_parser'

require 'minitest/autorun'

class Minitest::Test

  def address_parser
    @address_parser ||= UkAddressParser::AddressParser.new(address_string)
  end

  def address_string
    @address_string ||= address_components.values.join(address_join)
  end

  def address_components
    @address_components ||= {
      flat: flat,
      building_name: building_name,
      number_and_street: Faker::Address.street_address,
      town: Faker::Address.city,
      county: %w(Avon Worcestershire Lancashire Kent).sample,
      postcode: Faker::Address.zip_code
    }
  end

  def flat
    @flat ||= "Flat #{Faker::Number.between(1, 15)}"
  end

  def building_name
    @building_name ||= [
      Faker::StarWars.character,
      %w(Hall House Building Appartments).sample
    ].join(' ')
  end

  def address_join
    @address_join ||= ', '
  end

end

# Set faker so it uses British formats for postcodes etc.
require "faker"
Faker::Config.locale = "en-GB"

redpajama_set_name: RedPajamaGithub


text:
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.profiler;

import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.errorprone.annotations.concurrent.GuardedBy;
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

/** Thread to collect local cpu usage data and log into JSON profile. */
public class CollectLocalCpuUsage extends Thread {
  // TODO(twerth): Make these configurable.
  private static final Duration BUCKET_DURATION = Duration.ofSeconds(1);
  private static final long LOCAL_CPU_SLEEP_MILLIS = 200;

  private volatile boolean stopCpuUsage;
  private volatile boolean profilingStarted;

  @GuardedBy("this")
  private TimeSeries localCpuUsage;

  private Stopwatch stopwatch;

  @Override
  public void run() {
    stopwatch = Stopwatch.createStarted();
    synchronized (this) {
      localCpuUsage =
          new TimeSeries(
              /* startTimeMillis= */ stopwatch.elapsed().toMillis(), BUCKET_DURATION.toMillis());
    }
    OperatingSystemMXBean bean =
        (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    Duration previousElapsed = stopwatch.elapsed();
    long previousCpuTimeNanos = bean.getProcessCpuTime();
    profilingStarted = true;
    while (!stopCpuUsage) {
      try {
        Thread.sleep(LOCAL_CPU_SLEEP_MILLIS);
      } catch (InterruptedException e) {
        return;
      }
      Duration nextElapsed = stopwatch.elapsed();
      long nextCpuTimeNanos = bean.getProcessCpuTime();
      double deltaNanos = nextElapsed.minus(previousElapsed).toNanos();
      double cpuLevel = (nextCpuTimeNanos - previousCpuTimeNanos) / deltaNanos;
      synchronized (this) {
        if (localCpuUsage != null) {
          localCpuUsage.addRange(previousElapsed.toMillis(), nextElapsed.toMillis(), cpuLevel);
        }
      }
      previousElapsed = nextElapsed;
      previousCpuTimeNanos = nextCpuTimeNanos;
    }
  }

  public void stopCollecting() {
    Preconditions.checkArgument(!stopCpuUsage);
    stopCpuUsage = true;
    interrupt();
  }

  public synchronized void logCollectedData() {
    if (!profilingStarted) {
      return;
    }
    Preconditions.checkArgument(stopCpuUsage);
    long endTimeNanos = System.nanoTime();
    long elapsedNanos = stopwatch.elapsed(TimeUnit.NANOSECONDS);
    long startTimeNanos = endTimeNanos - elapsedNanos;
    int len = (int) (elapsedNanos / BUCKET_DURATION.toNanos()) + 1;
    double[] localCpuUsageValues = localCpuUsage.toDoubleArray(len);
    Profiler profiler = Profiler.instance();
    for (int i = 0; i < len; i++) {
      long eventTimeNanos = startTimeNanos + i * BUCKET_DURATION.toNanos();
      profiler.logEventAtTime(
          eventTimeNanos, ProfilerTask.LOCAL_CPU_USAGE, String.valueOf(localCpuUsageValues[i]));
    }
    localCpuUsage = null;
  }
}


text:
/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

//This code was borrowed from the Google Drive realtime-tasks sample.

zr.service('realtime', ['$q', '$rootScope', '$routeParams', 'config', 'drive',
	/**
	 * Handles document creation & loading for the app. Keeps only
	 * one document loaded at a time.
	 *
	 * @param $q
	 * @param $rootScope
	 * @param config
	 */
	function ($q, $rootScope, $routeParams, config, drive) {
		//Parameters for new project
		this.ideGraphical = false;
		this.gameId = null;

		this.id = null;
		this.document = null;
		var PROJ_INIT_TEXT = '\/\/Declare any variables shared between functions here\r\n\r\nvoid init(){\r\n\t\/\/This function is called once when your code is first loaded.\r\n\r\n\t\/\/IMPORTANT: make sure to set any variables that need an initial value.\r\n\t\/\/Do not assume variables will be set to 0 automatically!\r\n}\r\n\r\nvoid loop(){\r\n\t\/\/This function is called once per second.  Use it to control the satellite.\r\n}\r\n';

		/**
		 * Close the current document.
		 */
		this.closeDocument = function () {
			Blockly.Realtime.model_ = null;
			Blockly.Realtime.blocksMap_ = null;
			Blockly.Realtime.topBlocks_ = null;
			this.document.close();
			this.document = null;
			this.id = null;
		};

		/**
		 * Ensure the document is loaded.
		 *
		 * @param id
		 * @returns {angular.$q.promise}
		 */
		this.getDocument = function (id, dontReplace) {
			if (this.id === id) {
				return $q.when(this.document);
			} else if (this.document && !dontReplace) {
				this.closeDocument();
			}
			return this.load(id, dontReplace);
		};

		/**
		 * Creates a new document.
		 *
		 * @param title
		 * @returns {angular.$q.promise}
		 */
		this.createDocument = function (title, folder) {
			var deferred = $q.defer();
			var onComplete = function (result) {
				if (result && !result.error) {
					deferred.resolve(result);
				} else {
					deferred.reject(result);
				}
			};

			if(!folder) {
				folder = [];
			}

			gapi.client.request({
				'path': '/drive/v2/files',
				'method': 'POST',
				'body': JSON.stringify({
					title: title,
					mimeType: 'application/vnd.google-apps.drive-sdk',
					parents: folder
				})
			}).execute(onComplete);
			return deferred.promise;
		};

		var this_ = this;

		//Helper function for copyDocument
		var getCurrentFileData = function(id) {
			var deferredGet = $q.defer();
			var getDocData = function (result) {
				if (result && !result.error) {
					deferredGet.resolve(result);
				}
				else {
					deferredGet.reject(result);
				}
			};
			gapi.client.request({
				'path': 'drive/v2/files/'+id+'/realtime',
				'method': 'GET'
			}).execute(getDocData);

			return deferredGet.promise;
		}

		//Helper function for copyDocument
		var updateDocumentData = function(newFile, oldFile){
			var deferredUpdate = $q.defer();
			var onComplete = function (result) {
				if (!result){
					deferredUpdate.resolve(result);
				}
				else {
					deferredUpdate.reject(result);
				}
			};

			gapi.client.request({
				'path': 'upload/drive/v2/files/'+newFile.id+'/realtime',
				'method': 'PUT',
				'body': oldFile.data
			}).execute(onComplete);

			return deferredUpdate.promise;
		}

		/**
		 * Copies a document in place
		 */
		this.copyDocument = function (newTitle, id, folder) {
			var deferred = $q.defer();
			var onComplete = function (result) {
				if (result && !result.error){
					deferred.resolve(result);
				}
				else {
					deferred.resolve(result);
				}
			};
			if(!folder)
				folder = [];
			getCurrentFileData(id).then(function (oldFile) {
				this_.createDocument(newTitle, folder).then(function (copy) {
					updateDocumentData(copy, oldFile).then(function(){
						onComplete(copy);
					});
				});
			});

			return deferred.promise;
		};

		/**
		 * Actually load a document. If the document is new, initializes
		 * the model.
		 *
		 * @param id
		 * @returns {angular.$q.promise}
		 */
		this.load = function (id, dontReplace) {
			var deferred = $q.defer();
			var initialize = function (model) {
				var root = model.getRoot();
				var pages = model.createMap();
				root.set('pages', pages);
				root.set('gameId', this_.gameId);
				//Initialize the main pages
				if(!this_.ideGraphical) {
					root.set('graphical', false);
					pages.set('main', model.createString(PROJ_INIT_TEXT));
				}
				else {
					root.set('graphical', true);
					root.set('cglobals', model.createMap());
					root.set('procedures', model.createMap());
					var pageRoot = model.createMap();
					pages.set('main', pageRoot);
					//This code copied from blockly/core/realtime.js
					pageRoot.set('blocks', model.createMap());
					pageRoot.set('topBlocks', model.createList());
					pageRoot.set('type','loop');
					var pageRoot2 = model.createMap();
					pages.set('init', pageRoot2);
					pageRoot2.set('type','init');
					pageRoot2.set('blocks', model.createMap());
					pageRoot2.set('topBlocks', model.createList());
				}
				var log = model.createMap();
				root.set('log', log);
				//Get user name if available
				var displayName = 'Anonymous';
				drive.getUser(function(user) {
					displayName = user.displayName;
				});
				//Log entries are identified by timestamp, plus some random digits to avoid collisions
				var key = String(new Date().getTime() + Math.random());
				log.set(key, {
					user: displayName,
					title: 'Project created',
					content: ''
				});
			};
			var onLoad = function (document) {
				//dontReplace is for loading the opponent
				if(!dontReplace) {
					this_.setDocument(id, document);
					var model = document.getModel();
					Blockly.Realtime.model_ = model;
					Blockly.zr_cpp.C_GLOBAL_VARS = model.getRoot().get('cglobals');
					Blockly.zr_cpp.procedures = model.getRoot().get('procedures');
				}
				deferred.resolve(document);
				$rootScope.$digest();
			}.bind(this);
			var onError = function (error) {
				if (error.type === gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED) {
					$rootScope.$emit('todos.token_refresh_required');
				} else if (error.type === gapi.drive.realtime.ErrorType.CLIENT_ERROR) {
					$rootScope.$emit('todos.client_error');
				} else if (error.type === gapi.drive.realtime.ErrorType.NOT_FOUND) {
					deferred.reject(error);
					$rootScope.$emit('todos.not_found', id);
				}
				$rootScope.$digest();
			};
			gapi.drive.realtime.load(id, onLoad, initialize, onError);

			return deferred.promise;
		};

		/**
		 * Watches the model for any remote changes to force a digest cycle
		 *
		 * @param event
		 */
		this.changeListener = function (event) {
			if (!event.isLocal) {
				$rootScope.$digest();
			}
			window.lastEvent = event;
		};

		window.lastEvent = null;

		this.setDocument = function (id, document) {
			document.getModel().getRoot().addEventListener(
				gapi.drive.realtime.EventType.OBJECT_CHANGED,
				this.changeListener);
			this.document = document;
			this.id = id;
		};

		this.getDocAsString = function(modelRoot, countLines) {
			var str = '';
			var pages = modelRoot.get('pages');
			var keys = pages.keys().sort();
			var len = keys.length;
			var startLines = [];
			if(!modelRoot.get('graphical')) {
				for(var i = 0; i < len; i++) {
					if(countLines) {
						//Magic number: 24 is the offset needed to make line numbers match up with the zr.cpp template; needs to be changed if zr.cpp changes
						startLines.push({
							'name': keys[i],
							'line': str.split(/\r\n|\r|\n/).length + 24
						});
					}
					str = str + '//Begin page ' + keys[i] + '\n' + pages.get(keys[i]).getText() + '\n//End page ' + keys[i] + '\n';
				}
			}
			else {
				//Save the globals
				var oldGlobals = Blockly.zr_cpp.C_GLOBAL_VARS;
				//Load the target doc's globals
				Blockly.zr_cpp.C_GLOBAL_VARS = modelRoot.get('cglobals');
				for(var i = 0; i < len; i++) {
					var topBlocks = pages.get(keys[i]).get('topBlocks').asArray();
					if(topBlocks.length === 0) {
						//This will happen when the init page has not been initialized; it will be dealt with in finishFull
						continue;
					}
					var domText = topBlocks[0].xmlDom;
					var domObj = Blockly.Xml.textToDom(domText);
					var block = Blockly.Xml.domToSoloBlock(domObj);
					var code = Blockly.zr_cpp.blockToCode(block);
					if(countLines) {
						//Magic number: 24 is the offset needed to make line numbers match up with the zr.cpp template; needs to be changed if zr.cpp changes
						startLines.push({
							'name': keys[i],
							'line': str.split(/\r\n|\r|\n/).length + 24
						});
					}
					str = str + '//Begin page ' + keys[i] + '\n' + code + '\n//End page ' + keys[i] + '\n\n';
				}
				//Add globals and adjust line numbers
				if(countLines) {
					var lengthbefore = str.split(/\r\n|\r|\n/).length;
					str = Blockly.zr_cpp.finishFull(str);
					var diff = str.split(/\r\n|\r|\n/).length - lengthbefore;
					for(var i = startLines.length; i--;) {
						startLines[i].line += diff;
					}
				}
				else {
					str = Blockly.zr_cpp.finishFull(str);
				}
			}
			//Restore globals
			Blockly.zr_cpp.C_GLOBAL_VARS = oldGlobals;
			if(countLines) {
				return [str, startLines];
			}
			return str;
		};
	}]
);


text:
    #include "wx/bitmap.h"
#endif // WX_PRECOMP

#include "wx/stockitem.h"
#include "wx/tglbtn.h"
#include "wx/qt/private/converter.h"
#include "wx/qt/private/winevent.h"

#include <QtWidgets/QPushButton>

wxDEFINE_EVENT( wxEVT_TOGGLEBUTTON, wxCommandEvent );

wxIMPLEMENT_DYNAMIC_CLASS(wxBitmapToggleButton, wxToggleButton);

wxBitmapToggleButton::wxBitmapToggleButton()
{
}

wxBitmapToggleButton::wxBitmapToggleButton(wxWindow *parent,
               wxWindowID id,
               const wxBitmap& label,
               const wxPoint& pos,
               const wxSize& size,
               long style,
               const wxValidator& validator,
               const wxString& name)
{
    Create( parent, id, label, pos, size, style, validator, name );
}

bool wxBitmapToggleButton::Create(wxWindow *parent,
            wxWindowID id,
            const wxBitmap& label,
            const wxPoint& pos,
            const wxSize& size, long style,
            const wxValidator& validator,
            const wxString& name)
{
    if ( !wxToggleButton::Create(parent, id, wxString(), pos, size, style, validator, name) )
    {
        return false;
    }

    // this button is toggleable and has a bitmap label:
    if ( label.IsOk() )
    {
        SetBitmapLabel(label);

        // we need to adjust the size after setting the bitmap as it may be too
        // big for the default button size
        SetInitialSize(size);
    }

    return true;
}

//##############################################################################

wxIMPLEMENT_DYNAMIC_CLASS(wxToggleButton, wxControl);

wxToggleButton::wxToggleButton()
{
}

wxToggleButton::wxToggleButton(wxWindow *parent,
               wxWindowID id,
               const wxString& label,
               const wxPoint& pos,
               const wxSize& size,
               long style,
               const wxValidator& validator,
               const wxString& name)
{
    Create( parent, id, label, pos, size, style, validator, name );
}

bool wxToggleButton::Create(wxWindow *parent,
            wxWindowID id,
            const wxString& label,
            const wxPoint& pos,
            const wxSize& size, long style,
            const wxValidator& validator,
            const wxString& name)
{
    // create a checkable push button
    QtCreate(parent);
    m_qtPushButton->setCheckable(true);

    // this button is toggleable and has a text label
    SetLabel( wxIsStockID( id ) ? wxGetStockLabel( id ) : label );

    return QtCreateControl( parent, id, pos, size, style, validator, name );
}

void wxToggleButton::SetValue(bool state)
{
    m_qtPushButton->setChecked( state );
}

bool wxToggleButton::GetValue() const
{
    return m_qtPushButton->isChecked();
}


text:
package main

import (
	"net/http"
	"strconv"

	"github.com/antongulenko/http-isolation-proxy/services"
	"github.com/gorilla/mux"
)

func (store *AccountStore) show_stats(w http.ResponseWriter, r *http.Request) {
	stats := store.Stats()
	services.Http_respond_json(w, r, stats)
}

func (store *AccountStore) get_account(w http.ResponseWriter, r *http.Request) *Account {
	username := mux.Vars(r)["id"]
	if account := store.GetAccount(username); account == nil {
		services.Http_respond_error(w, r, "Account not found: "+username, http.StatusNotFound)
		return nil
	} else {
		return account
	}
}

func (store *AccountStore) optionally_commit_transaction(trans *Transaction, w http.ResponseWriter, r *http.Request) bool {
	commit := false
	if commitStr := r.FormValue("commit"); commitStr == "true" {
		commit = true
	}
	if commit {
		err := trans.Commit()
		if err != nil {
			services.Http_respond_error(w, r, "Unexpected failure to commit transaction: "+err.Error(), http.StatusInternalServerError)
			return false
		}
	}
	return true
}

func (store *AccountStore) get_value_query(w http.ResponseWriter, r *http.Request) (float64, bool) {
	value, err := strconv.ParseFloat(r.FormValue("value"), 64)
	if err != nil {
		services.Http_respond_error(w, r, "Failed to parse 'value' parameter to float: "+err.Error(), http.StatusBadRequest)
		return 0, false
	}
	return value, true
}

func (store *AccountStore) handle_deposit(w http.ResponseWriter, r *http.Request) {
	account := store.get_account(w, r)
	value, ok := store.get_value_query(w, r)
	if !ok {
		return
	}

	trans := store.NewTransaction(account, -value, nil)
	if store.optionally_commit_transaction(trans, w, r) {
		services.Http_respond(w, r, ([]byte)(trans.Id), http.StatusOK)
	}
}

func (store *AccountStore) handle_transfer(w http.ResponseWriter, r *http.Request) {
	account := store.get_account(w, r)
	value, ok := store.get_value_query(w, r)
	if !ok {
		return
	}

	target := r.FormValue("target")
	if target == "" {
		services.Http_respond_error(w, r, "Need 'target' string parameter", http.StatusBadRequest)
		return
	}
	targetAccount := store.GetAccount(target)

	trans := store.NewTransaction(account, value, targetAccount)
	if store.optionally_commit_transaction(trans, w, r) {
		services.Http_respond(w, r, ([]byte)(trans.Id), http.StatusOK)
	}
}

func (store *AccountStore) show_account(w http.ResponseWriter, r *http.Request) {
	if account := store.get_account(w, r); account != nil {
		services.Http_respond_json(w, r, account)
	}
}

func (store *AccountStore) get_transaction(w http.ResponseWriter, r *http.Request) *Transaction {
	trans_id := mux.Vars(r)["id"]
	var trans *Transaction
	var ok bool
	func() {
		store.transactionsLock.Lock()
		defer store.transactionsLock.Unlock()
		trans, ok = store.transactions[trans_id]
	}()
	if !ok || trans == nil {
		services.Http_respond_error(w, r, "Transaction not found: "+trans_id, http.StatusNotFound)
		return nil
	}
	return trans
}

func (store *AccountStore) show_transaction(w http.ResponseWriter, r *http.Request) {
	if trans := store.get_transaction(w, r); trans != nil {
		services.Http_respond_json(w, r, trans)
	}
}

func (store *AccountStore) cancel_transaction(w http.ResponseWriter, r *http.Request) {
	if trans := store.get_transaction(w, r); trans != nil {
		if err := trans.Cancel(); err != nil {
			services.Http_application_error(w, r, err)
		}
		services.Http_respond(w, r, nil, http.StatusOK)
	}
}

func (store *AccountStore) commit_transaction(w http.ResponseWriter, r *http.Request) {
	if trans := store.get_transaction(w, r); trans != nil {
		if err := trans.Commit(); err != nil {
			services.Http_application_error(w, r, err)
			return
		}
		services.Http_respond(w, r, nil, http.StatusOK)
	}
}

func (store *AccountStore) revert_transaction(w http.ResponseWriter, r *http.Request) {
	if trans := store.get_transaction(w, r); trans != nil {
		if err := trans.Revert(); err != nil {
			services.Http_application_error(w, r, err)
			return
		}
		services.Http_respond(w, r, nil, http.StatusOK)
	}
}


text:
package org.apache.drill.exec.physical.rowSet.model;

import org.apache.drill.exec.record.VectorContainer;
import org.apache.drill.exec.record.metadata.ColumnMetadata;
import org.apache.drill.exec.record.metadata.TupleMetadata;

/**
 * Common interface to access a tuple backed by a vector container or a
 * map vector. Provides a visitor interface to apply tasks such as vector
 * allocation, reader or writer creation, and so on. Allows either static
 * or dynamic vector allocation.
 *

 * The terminology used here:
 *

 *
Row set

 *
A collection of rows stored as value vectors. Elsewhere in
 * Drill we call this a "record batch", but that term has been overloaded to
 * mean the runtime implementation of an operator.

 *
Tuple

 *
The relational-theory term for a row. Drill maps have a fixed schema.
 * Impala, Hive and other tools use the term "structure" (or "struct") for
 * what Drill calls a map. A structure is simply a nested tuple, modeled
 * here by the same tuple abstraction used for rows.

 *
Column

 *
A column is represented by a vector (which may have internal
 * null-flag or offset vectors.) Maps are a kind of column that has an
 * associated tuple. Because this abstraction models structure, array
 * columns are grouped with single values: the array-ness is just cardinality.

 *
Visitor

 *
The visitor abstraction (classic Gang-of-Four pattern) allows adding
 * functionality without complicating the structure classes. Allows the same
 * abstraction to be used for the testing RowSet abstractions and
 * the scan operator "loader" classes.

 *
Metadata

 *
Metadata is simply data about data. Here, data about tuples and columns.
 * The column metadata mostly expands on that available in {@link org.apache.drill.exec.record.MaterializedField},
 * but also adds allocation hints.
 *

 *

 * This abstraction is the physical dual of a {@link VectorContainer}.
 * The vectors are "owned" by
 * the associated container. The structure here simply applies additional
 * metadata and visitor behavior to allow much easier processing that is
 * possible with the raw container structure.
 *

 * A key value of this abstraction is the extended {@link org.apache.drill.exec.record.metadata.TupleSchema}
 * associated with the structure.  Unlike a
 * {@link VectorContainer}, this abstraction keeps the schema in sync
 * with vectors as columns are added.
 *

 * Some future version may wish to merge the two concepts. That way, metadata
 * discovered by one operator will be available to another. Complex recursive
 * functions can be replace by a visitor with the recursion handled inside
 * implementations of this interface.
 *

 * Tuples provide access to columns by both index and name. Both the schema and
 * model classes follow this convention. Compared with the VectorContainer and
 * {@link org.apache.drill.exec.vector.complex.AbstractMapVector} classes, the vector index is a first-class concept:
 * the column model and schema are guaranteed to reside at the same index relative
 * to the enclosing tuple. In addition, name access is efficient using a hash
 * index.
 *

 * Visitor classes are defined by the "simple" (single batch) and "hyper"
 * (multi-batch) implementations to allow vector implementations to work
 * with the specifics of each type of batch.
 */

public interface TupleModel {

  /**
   * Common interface to access a column vector, its metadata, and its
   * tuple definition (for maps.) Provides a visitor interface for common
   * vector tasks.
   */

  public interface ColumnModel {
    ColumnMetadata schema();
    TupleModel mapModel();
  }

  /**
   * Tuple-model interface for the top-level row (tuple) structure.
   * Provides access to the {@link VectorContainer} representation of the
   * row set (record batch.)
   */

  public interface RowSetModel extends TupleModel {
    VectorContainer container();
  }

  TupleMetadata schema();
  int size();
  ColumnModel column(int index);
  ColumnModel column(String name);
}


text:
from StringIO import StringIO

from django.conf import settings
from django.core.management import get_commands, load_command_class, call_command
from django.core.management.base import BaseCommand, handle_default_options

from tastypie.exceptions import ImmediateHttpResponse

from management_api import logger

def get_command_list():
    commands = []

    commands_app_mapping = get_commands()

    exposed_commands = getattr(settings, 'MANAGEMENT_API_EXPOSED_COMMANDS', settings.INSTALLED_APPS)

    for command_name, app_name in commands_app_mapping.items():
        if command_name in exposed_commands:
            commands.append(command_name)

    return commands

def execute_command(command, *args):
    try:
        app_name = get_commands()[command]
    except KeyError:
        raise ImmediateHttpResponse('Error getting management command details')

    if isinstance(app_name, BaseCommand):
        # If the command is already loaded, use it directly.
        klass = app_name
    else:
        klass = load_command_class(app_name, command)

    command_args = list(args)

    parser = klass.create_parser(app_name, command)
    options, arguments = parser.parse_args(command_args)
    handle_default_options(options)

    options = options.__dict__

    command_result = StringIO()

    options.update({
        'interactive': False,
        'stdout': command_result
    })

    result = None

    try:
        klass.execute(*arguments, **options)
        command_result.seek(0)
        result = command_result.read()
    except Exception, e:
        logger.error(
            'Command: %s, args: %s, kwargs: %s. Error: %s',
            command,
            ', '.join(arguments),
            str(e)
        )
    except SystemExit as e:
        logger.error(
            'Command: %s, args: %s, kwargs: %s. Error: %s',
            command,
            ', '.join(arguments),
            str(e)
        )
        command_result.seek(0)
        result = command_result.read()

    return result


text:
static const char* const kSectionHeaders[] =
{
    "Audio:",
    "Bluetooth:",
    "Card Reader:",
    "Diagnostics:",
    "Disc Burning:",
    "Ethernet Cards:",
    "FireWire:",
    "Graphics/Displays:",
    "Hardware:",
    "Memory:",
    "Network:",
    "Printer Software:",
    "Printers:",
    "Serial-ATA:",
    "Software:",
    "Thunderbolt:",
    "USB:",
    "Wi-Fi:"
};

static const DFSystemProfileDataType kSectionTypes[] =
{
    DFSystemProfileData_Audio,
    DFSystemProfileData_Bluetooth,
    DFSystemProfileData_CardReader,
    DFSystemProfileData_Diagnostics,
    DFSystemProfileData_DiscBurning,
    DFSystemProfileData_EthernetCards,
    DFSystemProfileData_FireWire,
    DFSystemProfileData_GraphicsDisplays,
    DFSystemProfileData_Hardware,
    DFSystemProfileData_Memory,
    DFSystemProfileData_Network,
    DFSystemProfileData_PrinterSoftware,
    DFSystemProfileData_Printers,
    DFSystemProfileData_SerialATA,
    DFSystemProfileData_Software,
    DFSystemProfileData_Thunderbolt,
    DFSystemProfileData_USB,
    DFSystemProfileData_WiFi
};

static NSString* const kObscuredUserName = @"<user name>";
static NSString* const kObscuredUserFullName = @"<user full name>";

//-------------------------------------------------------------------------------------------------
@implementation DFSystemProfileFetcher
{
	NSTask* _scriptTask;
	NSPipe* _scriptPipe;
	NSString* _profile;
	BOOL _isDoneFetching;
    DFSystemProfileDataType _dataTypes;
    BOOL _anonymizeUser;
}

//-------------------------------------------------------------------------------------------------
+ (void)initialize
{
    NSAssert(sizeof(kSectionHeaders) / sizeof(kSectionHeaders[0]) == sizeof(kSectionTypes) / sizeof(kSectionTypes[0]), @"The number of section headers doesn't match the number of section types.");
}

//-------------------------------------------------------------------------------------------------
- (id)init
{
	self = [super init];
	if (self != nil)
	{
	}
	return self;
}

//-------------------------------------------------------------------------------------------------
- (void)dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver:self
													name:NSFileHandleReadToEndOfFileCompletionNotification
												  object:_scriptPipe.fileHandleForReading];
	[_scriptTask release];
	[_scriptPipe release];
	[_profile release];
	[super dealloc];
}

//-------------------------------------------------------------------------------------------------
- (void)scriptPipeDidComplete:(NSNotification*)notification
{
	if (notification != nil)
	{
		NSData* data = notification.userInfo[NSFileHandleNotificationDataItem];
		if (data != nil)
		{
			[_profile release];
			_profile = [[self filteredProfileFromData:data dataTypes:_dataTypes] retain];
		}
	}
	_isDoneFetching = YES;

    [self.delegate systemProfileFetcherDidFinish:self];
}

//-------------------------------------------------------------------------------------------------
- (NSString*)filteredProfileFromData:(NSData*)data
                           dataTypes:(DFSystemProfileDataType)dataTypes
{
    NSMutableString* profile = [NSMutableString string];

    const char* endOfString = (const char*)data.bytes + data.length;
    char* currLine = (char*)data.bytes;
    BOOL isCurrLineSectionHeader = YES;
    BOOL isSectionIncluded = YES;
    // cycle of characters
    for (char* cp = (char*)data.bytes; cp <= endOfString; ++cp)
    {
        // detect end of line
        if (*cp == '\n' || cp == endOfString)
        {
            // analyze line if not empty
            NSUInteger currLineLength = cp - currLine;
            if (currLineLength > 0)
            {
                // this is a section header
                if (isCurrLineSectionHeader)
                {
                    for (NSUInteger i = 0; i < sizeof(kSectionHeaders) / sizeof(kSectionHeaders[0]); ++i)
                    {
                        if (strncmp(currLine, kSectionHeaders[i], strlen(kSectionHeaders[i])) == 0)
                        {
                            isSectionIncluded = (kSectionTypes[i] & _dataTypes) != 0;
                            break;
                        }
                    }
                }
            }
            // include the line
            if (isSectionIncluded)
            {
                NSString* currLineString = [[[NSString alloc] initWithBytes:currLine length:currLineLength encoding:NSUTF8StringEncoding] autorelease];
                [profile appendString:currLineString];
                [profile appendString:@"\n"];
            }

            // new line
            currLine = cp + 1;
            isCurrLineSectionHeader = YES;
        }
        else
        {
            // detect section header
            if (cp == currLine)
            {
                if (*cp == ' ')
                {
                    isCurrLineSectionHeader = NO;
                }
            }
        }
    }

    // anonymize
    if (_anonymizeUser)
    {
        // remove full name
        NSString* userFullName = NSFullUserName();
        [profile replaceOccurrencesOfString:userFullName
                                 withString:kObscuredUserFullName
                                    options:NSCaseInsensitiveSearch
                                      range:NSMakeRange(0, profile.length)];
        // remove short name
        NSString* userName = NSUserName();
        [profile replaceOccurrencesOfString:userName
                                 withString:kObscuredUserName
                                    options:NSCaseInsensitiveSearch
                                      range:NSMakeRange(0, profile.length)];
    }

    return profile;
}

//-------------------------------------------------------------------------------------------------
- (void)fetchDataTypes:(DFSystemProfileDataType)dataTypes
         anonymizeUser:(BOOL)anonymizeUser
{
    BOOL success = NO;
    _anonymizeUser = anonymizeUser;
    _dataTypes = dataTypes;
	_isDoneFetching = NO;
    NSString* failureReason = nil;
    if (!self.class.canFetch)
    {
        failureReason = @"Cannot fetch system profile on OSX 10.7.x in sandboxed mode";
    }
    else
    {
        _scriptPipe = [[NSPipe pipe] retain];
		[[NSNotificationCenter defaultCenter] addObserver:self
												 selector:@selector(scriptPipeDidComplete:)
													 name:NSFileHandleReadToEndOfFileCompletionNotification
												   object:_scriptPipe.fileHandleForReading];

        _scriptTask = [[NSTask alloc] init];
        _scriptTask.launchPath = @"/usr/sbin/system_profiler";
        _scriptTask.arguments = @[@"-detailLevel", @"mini"];
        _scriptTask.standardOutput = _scriptPipe;
        @try
        {
            [_scriptTask launch];
            NSFileHandle* handle = _scriptPipe.fileHandleForReading;
            if (handle == nil)
            {
                failureReason = @"Invalid file handle";
            }
            else
            {
                [handle readToEndOfFileInBackgroundAndNotifyForModes:@[NSDefaultRunLoopMode,
                 NSModalPanelRunLoopMode]];
                success = YES;
            }
        }
        @catch (NSException* exception)
        {
            failureReason = exception.reason;
        }
    }

    if (!success)
    {
        NSLog(@"Failed to fetch system profile: %@", failureReason);
        // emulate async completion
        [self scriptPipeDidComplete:nil];
    }
}

//-------------------------------------------------------------------------------------------------
- (void)cancel
{
	[_scriptTask terminate];
}

//-------------------------------------------------------------------------------------------------
+ (BOOL)canFetch
{
    BOOL result = YES;
    // on 10.8, system profile seems to work somehow, even in sandbox, but not on 10.7 in sandbox
    if ([OSXVersion generation] < OSXGeneration_MountainLion)
    {
        if ([ApplicationSandboxInfo isSandboxed])
        {
            // currently, this would require a temporary exception entitlement, don't rely on it
            // maybe later implement it using xpc then check the corresponding entitlement here
            result = NO;
        }
    }
    return result;
}

@end


text:
var express = require('express');
var app = express();
var Datastore = require('nedb');
var db = {};
var wrapper = require('./lib/wrapper');

var port = process.argv[2] || 3000;
var root = "http://localhost:" + port;

db.movies = new Datastore({filename: 'db/movies', autoload: true});

//Add an index (if we try to add a duplicate title this will throw an error)
db.movies.ensureIndex({ fieldName: 'title', unique: true});

app.use(express.bodyParser());
app.use(function (req, res, next) {
    res.type('application/json');
    res.locals.wrap = wrapper.create({start: new Date()});
    next();
});

app.get('/movies', function (req, res) {
    db.movies.find({}, function (err, results) {
        if(err){
            res.json(500, {error: err});
            return;
        }
        // res.json(200,  res.locals.wrap(results.map(function (movie) {
        //     movie.links = { self:root + '/movies/' +movie._id};
        //     return movie;
        // }),{
        //     next: root+ '/movies?page=2'
        // }));
        res.json(200, res.locals.wrap({}, {item : results.map(function (movie) {
            return root + '/movies/' + movie._id;
        })}))
    });
});

app.post('/movies', function (req, res) {
    if(!req.body.title){
        res.status(400);
        res.json(400, {error: "A title is required tp create a movie"});
        return;
    }
    db.movies.insert({ title: req.body.title }, function (err, created) {
        if(err){
            res.json(500, err);
            return;
        }
        res.set('Location', root + '/movies/' + created._id);
        res.json(201, created)
    });
});

app.get('/movies/:id', function (req, res) {
    db.movies.findOne({ _id: req.params.id }, function (err, result) {
        if(err){
            res.json(500, err);
            return;
        }
        if(!result){
            res.json(404, {erro: "We did not find a movie with id " +req.params.id });
            return;
        }
        res.json(200, res.locals.wrap(result, { self: root + '/movies/' + req.params.id}));
    });
});

app.put('/movies/:id', function (req, res) {
    db.movies.update({ _id: req.params.id }, req.body, { upsert: false }, function (err, num, upsert) {
        if (err) {
            res.json(500, { error: err });
            return;
        }
        if (num === 0) {
            res.json(400, { error: { message: "No records were updated." }});
            return;
        }
        //res.send(204);
        res.json(200, { success: { message: "Sucessfully updated movie with ID " + req.params.id }});
    });
});
app.delete('/movies/:id', function (req, res) {
    db.movies.remove({ _id: req.params.id }, function (err, num) {
        if(err){
            res.json(500, err);
            return;
        }
        if(num === 0){
            res.json(404, {erro: "We did not find a movie with id " +req.params.id });
            return;
        }
        res.set('Link', root+'/movies; rel="collection"');
        res.send(204);
    });
})

app.listen(port);


text:
[![Greenkeeper badge](https://badges.greenkeeper.io/neverendingqs-sandbox/serverless-example.svg)](https://greenkeeper.io/)

# serverless-example

Simple Serverless Framework application based on their [hello world tutorial](https://serverless.com/framework/docs/providers/aws/examples/hello-world/node/).


text:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="de.rndm.droidFaker"
          android:versionCode="1"
          android:versionName="1.0">

    <!-- permissions -->
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS" />
    <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />

    <uses-sdk android:minSdkVersion="10"
            android:targetSdkVersion="19"/>
    <application android:label="@string/app_name"
                 android:allowBackup="true"
                 android:icon="@android:drawable/sym_def_app_icon">
        <activity android:name="MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
                android:name=".SettingsActivity"
                android:theme="@android:style/Theme.Black.NoTitleBar" >
        </activity>
    </application>
</manifest>