text:
/* startup_complete is only ever set if we're using the VNC clip facility *//**
 * xrdp: A Remote Desktop Protocol server.
 *
 * Copyright (C) Jay Sorg 2004-2015
 *
 * 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.
 *
 * libvnc
 *
 * The message definitions used in this source file can be found mostly
 * in RFC6143 - "The Remote Framebuffer Protocol".
 *
 * The clipboard messages from the RDP client side are mostly
 * described in [MS-RDPECLIP]
 */

#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif

#include "arch.h"
#include "vnc.h"
#include "vnc_clip.h"
#include "string_calls.h"
#include "ssl_calls.h"
#include "rfb.h"
#include "log.h"
#include "trans.h"
#include "ms-rdpbcgr.h"
#include "ms-rdpeclip.h"
#include "xrdp_constants.h"

/**
 * The formats we advertise as supported to the RDP client
 */
static const int
g_supported_formats[] =
{
    CF_UNICODETEXT,
    CF_LOCALE,
    CF_TEXT,
    /* Don't advertise CF_OEMTEXT - anything other than ASCII will be broken */
    /* CF_OEMTEXT, */
    0
};

/**
 * Data private to the VNC clipboard
 *
 * Note that this doesn't include the clip channel ID, as vnc.c needs
 * this to redirect virtual channel PDUs to this module */
struct vnc_clipboard_data
{
    struct stream *rfb_clip_s;
    int requested_clip_format; /* Last requested text format */
    int active_data_requests; /* Number of outstanding FORMAT_DATA_REQUESTs */
    struct stream *dechunker_s; /* Dechunker for the RDP clip channel */
    int capability_version;  /* Clipboard virt channel extension version */
    int capability_flags;    /* Channel capability flags */
    bool_t startup_complete; /* is the startup sequence done (1.3.2.1) */
};

/**
 * Summarise a stream contents in a way which allows two streams to
 * be easily compared
 */
struct stream_characteristics
{
    char digest[16];
    int length;
};

#ifdef USE_DEVEL_LOGGING
/***************************************************************************//**
 * Convert a CF_ constant to text
 *
 * @param CF_xxx constant
 * @param buff Scratchpad for storing a temporary string in
 * @param bufflen Length of the above
 *
 * @return string representation
 */
static const char *
cf2text(int cf, char *buff, int bufflen)
{
    const char *result;

    switch (cf)
    {
        case CF_UNICODETEXT:
            result = "CF_UNICODETEXT";
            break;

        case CF_LOCALE:
            result = "CF_LOCALE";
            break;

        case CF_TEXT:
            result = "CF_TEXT";
            break;

        case CF_OEMTEXT:
            result = "CF_OEMTEXT";
            break;

        default:
            g_snprintf(buff, bufflen, "CF_<0x%08x>", cf);
            result = buff;
    };

    return result;
}
#endif /* USE_DEVEL_LOGGING */

/***************************************************************************//**
 * Adds a CLIPRDR_HEADER ([MS-RDPECLIP] 2.2.1) to the data stream
 *
 * The location of the length is stored in the unused 'channel_hdr' field
 * of the data stream. When send_stream_to_clip_channel() is called,
 * we can use update the data length.
 *
 * @param s Output stream
 * @param msg_type Message Type
 * @param msg_flags Message flags
 */
static void
out_cliprdr_header(struct stream *s, int msg_type, int msg_flags)
{
    out_uint16_le(s, msg_type);
    out_uint16_le(s, msg_flags);
    /* Save the datalen location so we can update it later */
    s_push_layer(s, channel_hdr, 4);
}

/***************************************************************************//**
 * Sends the contents of a stream buffer to the clipboard channel
 *
 * Stream contents are chunked appropriately if they are too big to
 * fit in a single PDU
 *
 * The stream object cliprdr datalen header field is updated by this call.
 *
 * @param v VNC object
 * @param s stream buffer
 *
 * @pre stream buffer must have been initialised with a call to
 *      out_cliprdr_header()
 * @pre Stream is terminated with s_mark_end()
 */
static int
send_stream_to_clip_channel(struct vnc *v, struct stream *s)
{
    int rv = 0;
    int datalen = 0; /* cliprdr PDU datalen field */
    int pos = 0;
    int pdu_len = 0; /* Length of channel PDU */
    int total_data_len = (int)(s->end - s->data);
    int flags;
    int msg_type;
    int msg_flags;

    /* Use the pointer saved by out_cliprdr_header() to
     * write the cliprdr PDU length */
    s_pop_layer(s, channel_hdr);
    datalen = (int)(s->end - s->p) - 4;
    out_uint32_le(s, datalen);

    /* Read the other fields of the cliprdr header for logging */
    s->p = s->data;
    in_uint16_le(s, msg_type);
    in_uint16_le(s, msg_flags);
    LOG(LOG_LEVEL_DEBUG, "Sending cliprdr PDU type:%s flags:%d datalen:%d",
        CB_PDUTYPE_TO_STR(msg_type), msg_flags, datalen);

    for ( ; rv == 0 && pos < total_data_len ; pos += pdu_len)
    {
        pdu_len = MIN(CHANNEL_CHUNK_LENGTH, (total_data_len - pos));

        /* Determine chunking flags for this PDU (MS-RDPBCGR 3.1.5.2.1) */
        if (pos == 0)
        {
            if ((pos + pdu_len) == total_data_len)
            {
                /* Only one chunk */
                flags = (XR_CHANNEL_FLAG_FIRST | XR_CHANNEL_FLAG_LAST);
            }
            else
            {
                /* First chunk of several */
                flags = (XR_CHANNEL_FLAG_FIRST | XR_CHANNEL_FLAG_SHOW_PROTOCOL);
            }
        }
        else if ((pos + pdu_len) == total_data_len)
        {
            /* Last chunk of several */
            flags = (XR_CHANNEL_FLAG_LAST | XR_CHANNEL_FLAG_SHOW_PROTOCOL);
        }
        else
        {
            /* Intermediate chunk of several */
            flags = XR_CHANNEL_FLAG_SHOW_PROTOCOL;
        }
        rv = v->server_send_to_channel(v, v->clip_chanid,
                                       s->data + pos, pdu_len,
                                       total_data_len, flags);
    }

    return rv;
}

/***************************************************************************//**
 * Counts the occurrences of a character in a stream
 * @param s stream
 * @param c character
 * @return occurrence count
 */
static int
char_count_in(const struct stream *s, char c)
{
    int rv = 0;
    const char *p = s->data;
    const char *end = s->end;

    while ((p = g_strnchr(p, c, end - p)) != NULL)
    {
        ++rv;
        ++p; /* Skip counted character */
    }

    return rv;
}

/***************************************************************************//**
 * Searches a Format List PDU for a preferred text format
 *
 * On entry, the stream contains a formatListData object
 *
 * @param v VNC module
 * @param msg_flags clipHeader msgFlags field
 * @params s formatListData object.
 * @return Preferred text format, or 0 if not found
 */
static int
find_preferred_text_format(struct vnc *v, int msg_flags, struct stream *s)
{
    int seen_cf_unicodetext = 0;
    int seen_cf_text = 0;
    int format_id;
#ifdef USE_DEVEL_LOGGING
    char scratch[64];
#endif

    while (s_check_rem(s, 4))
    {
        in_uint32_le(s, format_id);

        if ((v->vc->capability_flags & CB_USE_LONG_FORMAT_NAMES) == 0)
        {
            /* Short format name */
            int skip = MIN(s_rem(s), 32);
            in_uint8s(s, skip);
        }
        else
        {
            /* Skip a wsz string */
            int wc = 1;
            while (s_check_rem(s, 2) && wc != 0)
            {
                in_uint16_le(s, wc);
            }
        }

        LOG_DEVEL(LOG_LEVEL_INFO, "VNC: Format id %s available"
                  " from RDP client",
                  cf2text(format_id, scratch, sizeof(scratch)));

        switch (format_id)
        {
            case CF_UNICODETEXT:
                seen_cf_unicodetext = 1;
                break;

            case CF_TEXT:
                seen_cf_text = 1;
                break;
        }
    }

    /* Prefer Unicode (UTF-16), as it's most easily converted to
     * the ISO-8859-1 supported by the VNC clipboard */
    return
        (seen_cf_unicodetext != 0 ? CF_UNICODETEXT :
         seen_cf_text != 0 ? CF_TEXT :
         /* Default */ 0);
}

/******************************************************************************/
static int
handle_cb_format_list(struct vnc *v, int msg_flags, struct stream *s)
{
    struct stream *out_s;
    int format;
    int rv = 0;
#ifdef USE_DEVEL_LOGGING
    char scratch[64];
#endif

    /* This is the last stage of the startup sequence in MS-RDPECLIP 1.3.2.1,
     * although it does occur at other times */
    v->vc->startup_complete = 1;

    make_stream(out_s);

    /* Reply to the caller */
    init_stream(out_s, 64);
    out_cliprdr_header(out_s, CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK);
    s_mark_end(out_s);
    send_stream_to_clip_channel(v, out_s);

    /* Send a CB_DATA_REQUEST message to the cliprdr channel,
     * if a suitable text format is available */
    if ((format = find_preferred_text_format(v, msg_flags, s)) != 0)
    {
        LOG_DEVEL(LOG_LEVEL_INFO,
                  "Asking RDP client for clip data format=%s",
                  cf2text(format, scratch, sizeof(scratch)));
        v->vc->requested_clip_format = format;
        ++v->vc->active_data_requests;
        init_stream(out_s, 64);
        out_cliprdr_header(out_s, CB_FORMAT_DATA_REQUEST, 0);
        out_uint32_le(out_s, format);
        s_mark_end(out_s);
        send_stream_to_clip_channel(v, out_s);
    }
    free_stream(out_s);

    return rv;
}

/***************************************************************************//**
 * Computes the characteristics of a stream.
 *
 * This can be used to tell if a stream has changed or two streams are
 * the same
 *
 * @param s Stream
 * @param[out] chars Resulting characteristics of stream
 */
static void
compute_stream_characteristics(const struct stream *s,
                               struct stream_characteristics *chars)
{
    void *info = ssl_md5_info_create();
    ssl_md5_clear(info);
    if (s->data != NULL && s->end != NULL)
    {
        chars->length = (int)(s->end - s->data);
        ssl_md5_transform(info, s->data, chars->length);
    }
    else
    {
        chars->length = 0;
    }
    ssl_md5_complete(info, chars->digest);
    ssl_md5_info_delete(info);
}

/***************************************************************************//**
 * Compare two stream characteristics structs for equality
 *
 * @param a characteristics of first stream
 * @param b characteristics of second stream
 * @result != 0 if characteristics are equal
 */
static int
stream_characteristics_equal(const struct stream_characteristics *a,
                             const struct stream_characteristics *b)
{
    return (a->length == b->length &&
            g_memcmp(a->digest, b->digest, sizeof(a->digest)) == 0);
}

/******************************************************************************/
static int
handle_cb_format_data_request(struct vnc *v, struct stream *s)
{
    int format = 0;
    struct stream *out_s;
    int i;
    struct vnc_clipboard_data *vc = v->vc;
    int rv = 0;
    int msg_flags = CB_RESPONSE_OK;
    int lf_count;
    int alloclen = 64;
#ifdef USE_DEVEL_LOGGING
    char scratch[64];
#endif

    if (s_check_rem(s, 4))
    {
        in_uint32_le(s, format);
    }

    LOG_DEVEL(LOG_LEVEL_INFO, "RDP client requested data format=%s",
              cf2text(format, scratch, sizeof(scratch)));

    make_stream(out_s);

    /* For all formats, we need to convert to Windows carriage control,
     * so we need to know how many '\n' characters become '\r\n' */
    lf_count = char_count_in(vc->rfb_clip_s, '\n');

    /* If we're writing a big string, we need to increase the alloclen
     * for the return PDU. We can also vet the requested format here */
    switch (format)
    {
        case CF_TEXT:
            /* We need to allocate enough characters to hold the string
             * with '\n' becoming '\r\n' and also for a terminator. */
            alloclen += vc->rfb_clip_s->size + lf_count + 1;
            break;

        case CF_UNICODETEXT:
            /* As CF_TEXT, but twice as much, as each ANSI character maps to
             * two octets */
            alloclen += (vc->rfb_clip_s->size + lf_count + 1) * 2;
            break;

        case CF_LOCALE:
            break;

        default:
            /* No idea what this is */
            msg_flags = CB_RESPONSE_FAIL;
    }

    /* Allocate the stream and check for failure as the string could be
     * essentially unlimited in length */
    init_stream(out_s, alloclen);
    if (out_s->data == NULL)
    {
        LOG(LOG_LEVEL_ERROR,
            "Memory exhausted allocating %d bytes for clip data response",
            alloclen);
        rv = 1;
    }
    else
    {
        /* Write the packet header.... */
        out_cliprdr_header(out_s, CB_FORMAT_DATA_RESPONSE, msg_flags);

        /* ...and any data */
        switch (format)
        {
            case CF_LOCALE:
                /*
                 * This is undocumented.
                 *
                 * Reverse engineering by firing this request off to
                 * a Microsoft client suggests this is a code from
                 * [MS-LCID]. 0x409 maps to en-us which uses codepage
                 * 1252. This is a close enough match to ISO8859-1 as used
                 * by RFB */
                out_uint32_le(out_s, 0x409);
                break;

            case CF_TEXT:
                for (i = 0; i < vc->rfb_clip_s->size; ++i)
                {
                    char c = vc->rfb_clip_s->data[i];
                    if (c == '\n')
                    {
                        out_uint8(out_s, '\r');
                    }
                    out_uint8(out_s, c);
                }

                out_uint8s(out_s, 1);
                break;

            case CF_UNICODETEXT:
                /* The VNC clipboard format (ISO 8859-1)
                   maps directly to UTF-16LE by moving over the bottom 8 bits,
                   and setting the top 8 bits to zero */
                for (i = 0; i < vc->rfb_clip_s->size; ++i)
                {
                    char c = vc->rfb_clip_s->data[i];
                    if (c == '\n')
                    {
                        out_uint8(out_s, '\r');
                        out_uint8(out_s, 0);
                    }
                    out_uint8(out_s, c);
                    out_uint8(out_s, 0);
                }

                out_uint8s(out_s, 2);
                break;
        }

        s_mark_end(out_s);
        send_stream_to_clip_channel(v, out_s);
        free_stream(out_s);
    }

    return rv;
}

/******************************************************************************/
static int
handle_cb_format_data_response(struct vnc *v, struct stream *s)
{
    int rv = 0;

    struct vnc_clipboard_data *vc = v->vc;

    /* The [MS-RDPECLIP] specification lets a new CB_FORMAT_LIST PDU turn
     * up before we've received a response to a CB_FORMAT_DATA_REQUEST.
     * As a result, there might be more than one CB_FORMAT_DATA_RESPONSE
     * PDUs in-flight. We handle this by ignoring all but the last PDU
     * we're expecting
     */
    if (vc->active_data_requests > 0 && --vc->active_data_requests == 0)
    {
        struct stream *out_s;
        int length;
        char c;
        char lastc;
        int wc;
        unsigned int out_of_range = 0;

        /* We've got a copy of the current VNC paste buffer in
         * vc->rfb_clip_s. Since we're about to change the VNC paste
         * buffer anyway, we'll use this to construct the ISO8859-1
         * text, and then send it to the VNC server
         *
         * We size the buffer as follows:-
         * TEXT Use the same size buffer.
         * UTF-16 - Use half the size
         *
         * In all cases this is big enough, or a little over when removal
         * of `\r` characters is taken into account */
        if  (vc->requested_clip_format == CF_UNICODETEXT)
        {
            length = s_rem(s) / 2;
        }
        else
        {
            length = s_rem(s);
        }

        init_stream(vc->rfb_clip_s, length);
        if (vc->rfb_clip_s->data == NULL)
        {
            LOG(LOG_LEVEL_ERROR,
                "Memory exhausted allocating %d bytes for clip buffer",
                length);
            rv = 1;
        }
        else
        {
            switch (vc->requested_clip_format)
            {
                case CF_TEXT:
                    lastc = '\0';
                    while (s_check_rem(s, 1))
                    {
                        in_uint8(s, c);
                        if (c == '\n' && lastc == '\r')
                        {
                            /* Overwrite the `\r' */
                            --vc->rfb_clip_s->p;
                        }
                        out_uint8(vc->rfb_clip_s, c);
                        lastc = c;
                    }
                    break;

                case CF_UNICODETEXT:
                    lastc = '\0';
                    while (s_check_rem(s, 2))
                    {
                        in_uint16_le(s, wc);
                        if (wc / 0x100 == 0)
                        {
                            /* Valid ISO8859-1 character in bottom 8 bits */
                            c = wc % 0x100;
                            if (c == '\n' && lastc == '\r')
                            {
                                /* Overwrite the `\r' */
                                --vc->rfb_clip_s->p;
                            }
                            out_uint8(vc->rfb_clip_s, c);
                            lastc = c;
                        }
                        else
                        {
                            /* Character can't be represented in ISO8859-1 */
                            ++out_of_range;
                            if (wc & 0xdc00 && wc <= 0xdfff)
                            {
                                /* Character is start of a surrogate pair */
                                if (s_check_rem(s, 2))
                                {
                                    in_uint16_le(s, wc);
                                }
                            }
                        }
                    }

                    if (out_of_range > 0)
                    {
                        LOG(LOG_LEVEL_WARNING,
                            "VNC: %u out-of-range Unicode characters"
                            " could not be moved to the VNC clipboard",
                            out_of_range);
                    }
                    break;

            }

            /* Remove a terminator at the end, as RFB doesn't need it */
            if (vc->rfb_clip_s->p != vc->rfb_clip_s->data &&
                    *(vc->rfb_clip_s->p - 1) == '\0')
            {
                --vc->rfb_clip_s->p;
            }
            s_mark_end(vc->rfb_clip_s);

            /* Update the VNC server */
            make_stream(out_s);
            length = (unsigned int)(vc->rfb_clip_s->end -
                                    vc->rfb_clip_s->data);
            init_stream(out_s, 1 + 3 + 4 + length);
            out_uint8(out_s, RFB_C2S_CLIENT_CUT_TEXT);
            out_uint8s(out_s, 3);  /* padding */
            out_uint32_be(out_s, length);
            out_uint8p(out_s, vc->rfb_clip_s->data, length);
            s_mark_end(out_s);
            lib_send_copy(v, out_s);
            free_stream(out_s);
        }
    }

    return rv;
}

/******************************************************************************/
static int
handle_cb_caps(struct vnc *v, struct stream *s)
{
    int rv = 0;
    int i;
    int capset_count;
    int capset_type;
    int capset_length;
    int version;
    int flags;

    if (!s_check_rem_and_log(s, 4, "Reading clip capabilities"))
    {
        rv = 1;
    }
    else
    {
        in_uint16_le(s, capset_count);
        in_uint8s(s, 2); /* pad */

        for (i = 0; i < capset_count && rv == 0; ++i)
        {
            if (!s_check_rem_and_log(s, 4, "Reading capability set"))
            {
                rv = 1;
                break;
            }

            in_uint16_le(s, capset_type); /* Length includes these two fields */
            in_uint16_le(s, capset_length);
            capset_length -= 4; /* Account for last two fields */

            switch (capset_type)
            {
                case CB_CAPSTYPE_GENERAL:
                    if (!s_check_rem_and_log(s, 8, "Reading general cap set"))
                    {
                        rv = 1;
                    }
                    else
                    {
                        in_uint32_le(s, version); /* version */
                        in_uint32_le(s, flags); /* generalFlags */
                        capset_length -= 8;

                        /* Update our own capability fields */
                        if (version > 0 && version < v->vc->capability_version)
                        {
                            v->vc->capability_version = version;
                        }
                        v->vc->capability_flags &= flags;

                        LOG(LOG_LEVEL_DEBUG,
                            "Agreed MS-RDPECLIP capability"
                            "version=%d flags=%08x with RDP client",
                            v->vc->capability_version,
                            v->vc->capability_flags);
                    }
                    break;

                default:
                    LOG(LOG_LEVEL_WARNING, "clipboard_process_clip_caps: "
                        "unknown capabilitySetType %d", capset_type);
                    break;
            }

            /* Check for padding at the end of the set */
            if (capset_length > 0)
            {
                if (!s_check_rem_and_log(s, capset_length, "cap set padding"))
                {
                    rv = 1;
                }
                else
                {
                    in_uint8s(s, capset_length);
                }
            }
        }
    }

    return rv;
}

/***************************************************************************//**
 * Send a format list PDU to the RDP client
 *
 * Described in [MS-RDPECLIP] 2.2.3.1
 *
 * @param v VNC structure
 */
static void
send_format_list(struct vnc *v)
{
    struct vnc_clipboard_data *vc = v->vc;
    int use_long_names = vc->capability_flags & CB_USE_LONG_FORMAT_NAMES;
    struct stream *out_s;
    unsigned int i = 0;
    int format;

    make_stream(out_s);
    init_stream(out_s, 8192);
    out_cliprdr_header(out_s, CB_FORMAT_LIST, use_long_names);

    while ((format = g_supported_formats[i++]) != 0)
    {
        if (use_long_names)
        {
            /* Long format name [MS-RDPECLIP] 2.2.3.1.2.1 */
            out_uint32_le(out_s, format);
            out_uint8s(out_s, 2); /* wsz terminator */
        }
        else
        {
            /* Short format name [MS-RDPECLIP] 2.2.3.1.1.1 */
            out_uint32_le(out_s, format);
            out_uint8s(out_s, 32);
        }
    }
    s_mark_end(out_s);
    send_stream_to_clip_channel(v, out_s);
    free_stream(out_s);
}

/******************************************************************************/
void
vnc_clip_init(struct vnc *v)
{
    v->vc = (struct vnc_clipboard_data *)g_malloc(sizeof(*v->vc), 1);
    make_stream(v->vc->rfb_clip_s);
}

/******************************************************************************/
void
vnc_clip_exit(struct vnc *v)
{
    if (v != NULL && v->vc != NULL)
    {
        free_stream(v->vc->rfb_clip_s);
        free_stream(v->vc->dechunker_s);
        g_free(v->vc);
    }
}

/******************************************************************************/
int
vnc_clip_process_eclip_pdu(struct vnc *v, struct stream *s)
{
    int type;
    int msg_flags;
    int datalen;
    int rv = 0;

    /* Ignore PDUs with no complete header */
    if (s_check_rem_and_log(s, 8, "MS-RDPECLIP PDU Header"))
    {
        in_uint16_le(s, type);
        in_uint16_le(s, msg_flags);
        in_uint32_le(s, datalen);

        LOG(LOG_LEVEL_DEBUG, "got clip data type %s msg_flags %d length %d",
            CB_PDUTYPE_TO_STR(type), msg_flags, datalen);
        LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "clipboard data",
                          s->p, s->end - s->p);

        /* Check the PDU is contained in the stream */
        if (!s_check_rem_and_log(s, datalen, "MS-RDPECLIP PDU"))
        {
            datalen = s_rem(s);
        }
        else
        {
            /* Truncate the PDU to the data length so we can use the
             * normal functions to parse the PDU */
            s->end = s->p + datalen;
        }

        switch (type)
        {
            case CB_FORMAT_LIST:
                rv = handle_cb_format_list(v, msg_flags, s);
                break;

            case CB_FORMAT_LIST_RESPONSE:
                /* We don't need to do anything with this */
                break;

            case CB_FORMAT_DATA_REQUEST:
                rv = handle_cb_format_data_request(v, s);
                break;

            case CB_FORMAT_DATA_RESPONSE:
                if (msg_flags == CB_RESPONSE_OK)
                {
                    rv = handle_cb_format_data_response(v, s);
                }
                break;

            case CB_CLIP_CAPS:
                rv = handle_cb_caps(v, s);
                break;
        }
    }

    return rv;
}

/******************************************************************************/
/**
 * Process a [MS-RDPBCGR] 2.2.6.1 Virtual Channel PDU and re-assemble the
 * data chunks as needed - see 3.1.5.2.2.1
 */
int
vnc_clip_process_channel_data(struct vnc *v, char *data, int size,
                              int total_size, int flags)
{
    int rv = 1;
    struct vnc_clipboard_data *vc = v->vc;
    bool_t first = ((flags & XR_CHANNEL_FLAG_FIRST) != 0);
    bool_t last = ((flags & XR_CHANNEL_FLAG_LAST) != 0);

    if (size > total_size)
    {
        /* This should never happen */
        LOG(LOG_LEVEL_ERROR,
            "Ignoring bad PDU chunk data on clip channel");
    }
    else if (first && vc->dechunker_s != NULL)
    {
        /*
         * If this packet is marked as 'first', we should not be
         * dechunking data already */
        LOG(LOG_LEVEL_ERROR, "Packet chunking start state error");
        free_stream(vc->dechunker_s);
        vc->dechunker_s = NULL;
    }
    else if (!first && vc->dechunker_s == NULL)
    {
        /*
         * This is not the first packet, but the dechunker is not active */
        LOG(LOG_LEVEL_ERROR, "Packet chunking end state error");
    }
    else if (first && last)
    {
        /* this is a complete packet
         * Construct a temp stream for the complete packet, and pass it
         * to the application */
        struct stream packet_s = {0};

        packet_s.data = data;
        packet_s.size = size;
        packet_s.end = packet_s.data + size;
        packet_s.p = packet_s.data;
        rv = vnc_clip_process_eclip_pdu(v, &packet_s);
    }
    else if (first)
    {
        /* Start de-chunking the data */
        make_stream(vc->dechunker_s);
        init_stream(vc->dechunker_s, (int)total_size);

        /* MS-RDPBCGR 3.1.5.2.2.1 states:-
         *
         *     A reassembly buffer MUST be created by the virtual channel
         *     endpoint using the size specified by totalLength when
         *     the first chunk is received.
         *
         * The 'total_size' can be several GB in size, so we really need
         * to check for an allocation failure here */
        if (vc->dechunker_s->data == NULL)
        {
            LOG(LOG_LEVEL_ERROR,
                "Memory exhausted dechunking a %u byte virtual channel PDU",
                total_size);
        }
        else
        {
            out_uint8a(vc->dechunker_s, data, size);
            rv = 0;
        }
    }
    else if (s_check_rem_out_and_log(vc->dechunker_s,
                                     size, "VNC dechunker:"))
    {
        out_uint8a(vc->dechunker_s, data, size);
        /* At the end? */
        if (last)
        {
            s_mark_end(vc->dechunker_s);
            vc->dechunker_s->p = vc->dechunker_s->data;

            /* Call the app and reset the dechunker */
            rv = vnc_clip_process_eclip_pdu(v, vc->dechunker_s);
            free_stream(vc->dechunker_s);
            vc->dechunker_s = NULL;
        }
        else
        {
            rv = 0;
        }
    }

    return rv;
}

/******************************************************************************/
/* clip data from the vnc server */
int
vnc_clip_process_rfb_data(struct vnc *v)
{
    struct vnc_clipboard_data *vc = v->vc;
    struct stream *s;
    int size;
    int rv;

    make_stream(s);
    init_stream(s, 8192);
    rv = trans_force_read_s(v->trans, s, 7);

    if (rv == 0)
    {
        in_uint8s(s, 3);
        in_uint32_be(s, size);

        if (v->clip_chanid < 0 || v->server_chansrv_in_use(v))
        {
            /* Skip this message */
            LOG(LOG_LEVEL_DEBUG, "Skipping %d clip bytes from RFB", size);
            rv = skip_trans_bytes(v->trans, size);
        }
        else
        {
            struct stream_characteristics old_chars;
            struct stream_characteristics new_chars;

            /* Compute the characteristics of the existing data */
            compute_stream_characteristics(vc->rfb_clip_s, &old_chars);

            /* Lose any existing RFB clip data */
            free_stream(vc->rfb_clip_s);
            vc->rfb_clip_s = 0;

            make_stream(vc->rfb_clip_s);
            if (size < 0)
            {
                /* This shouldn't happen - see Extended Clipboard
                 * Pseudo-Encoding */
                LOG(LOG_LEVEL_ERROR, "Unexpected size %d for RFB data", size);
                rv = 1;
            }
            else if (size == 0)
            {
                LOG(LOG_LEVEL_DEBUG, "RFB clip data cleared by VNC server");
            }
            else
            {
                init_stream(vc->rfb_clip_s, size);
                if (vc->rfb_clip_s->data == NULL)
                {
                    LOG(LOG_LEVEL_ERROR,
                        "Memory exhausted allocating %d bytes"
                        " for RFB clip data",
                        size);
                    rv = 1;
                }
                else
                {
                    LOG(LOG_LEVEL_DEBUG, "Reading %d clip bytes from RFB",
                        size);
                    rv = trans_force_read_s(v->trans, vc->rfb_clip_s, size);
                }
            }

            /* Consider telling the RDP client about the update only if we've
             * completed the startup handshake */
            if (rv == 0 && vc->startup_complete)
            {
                /* Has the data actually changed ? */
                compute_stream_characteristics(vc->rfb_clip_s, &new_chars);
                if (stream_characteristics_equal(&old_chars, &new_chars))
                {
                    LOG_DEVEL(LOG_LEVEL_INFO, "RFB Clip data is unchanged");
                }
                else
                {
                    LOG_DEVEL(LOG_LEVEL_INFO, "RFB Clip data is updated");
                    send_format_list(v);
                }
            }
        }
    }

    free_stream(s);
    return rv;
}

/******************************************************************************/
int
vnc_clip_open_clip_channel(struct vnc *v)
{
    v->clip_chanid = v->server_get_channel_id(v, CLIPRDR_SVC_CHANNEL_NAME);

    if (v->server_chansrv_in_use(v))
    {
        /*
         * The clipboard is provided by chansrv, if at all - it may of
         * course be disabled there.
         */
        LOG(LOG_LEVEL_INFO, "VNC: Clipboard (if available) is provided "
            "by chansrv facility");
    }
    else if (v->clip_chanid < 0)
    {
        LOG(LOG_LEVEL_INFO, "VNC: Clipboard is unavailable");
    }
    else
    {
        struct stream *s;

        LOG(LOG_LEVEL_INFO, "VNC: Clipboard supports ISO-8859-1 text only");

        make_stream(s);
        init_stream(s, 8192);

        v->vc->capability_version = CB_CAPS_VERSION_2;
        v->vc->capability_flags = CB_USE_LONG_FORMAT_NAMES;
        /**
         * Send two PDUs to initialise the channel. The client should
         * respond with a CB_CLIP_CAPS PDU of its own. See [MS-RDPECLIP]
         * 1.3.2.1 */
        out_cliprdr_header(s, CB_CLIP_CAPS, 0);
        out_uint16_le(s, 1); /* #cCapabilitiesSets */
        out_uint16_le(s, 0); /* pad1 */
        /* CLIPRDR_GENERAL_CAPABILITY */
        out_uint16_le(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType */
        out_uint16_le(s, 12); /* lengthCapability */
        out_uint32_le(s, v->vc->capability_version);
        out_uint32_le(s, v->vc->capability_flags);
        s_mark_end(s);
        send_stream_to_clip_channel(v, s);

        /* Send the monitor ready PDU */
        init_stream(s, 0);
        out_cliprdr_header(s, CB_MONITOR_READY, 0);
        s_mark_end(s);
        send_stream_to_clip_channel(v, s);

        free_stream(s);
        /* Need to complete the startup handshake before we send formats */
        v->vc->startup_complete = 1;
    }

    return 0;
}


text:
from django import template
import datetime
import pytz # for time zone handleing

register = template.Library()

@register.tag(name="timePosted")
def do_time_since(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        tag_name, date_to_format = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0])
    return TimePostedNode(date_to_format)

class TimePostedNode(template.Node):
    def __init__(self, date_to_format):
        self.date_to_format = template.Variable(date_to_format)
    def render(self, context):
        try:
            d = self.date_to_format.resolve(context)
            delta = datetime.datetime.now(pytz.utc) - d
            if delta.days > 7:
                return "Posted %s days ago." %(delta.days)
            elif delta.seconds//3600 > 1:
                return "Posted %s days and %s minutes ago." %(delta.days, delta.seconds//3600)
            else:
                 return "Posted %s seconds ago." %((delta.seconds//60)%60)
        except template.VariableDoesNotExist:
            return ''

@register.tag(name="pctChange")
def do_pctChange(parser, token):
    try:
        # split_contents() knows not to split quoted strings.
        tag_name, args = token.split_contents()
        end, begin = args.split()
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires that arguments are in quotes" % token.contents.split()[0])
    #slice to remove quotes
    return pctChangeNode(end[1:], begin[:-1])

class pctChangeNode(template.Node):
    def __init__(self, end, begin):
        self.begin = template.Variable(begin)
        self.end = template.Variable(end)
    def render(self, context):
        try:
            begin = self.begin.resolve(context)
            end = self.end.resolve(context)
            return "%0.2f%%" %(((end - begin)/ float(begin)) * 100)
        except template.VariableDoesNotExist:
            return ''

redpajama_set_name: RedPajamaGithub


text:
Public Class BandClass
    Private _maxBands As Integer = 6
    Private _localArray() As String

    Public Sub New(ByRef aBandArray() As String)
        ReDim aBandArray(Me._maxBands - 1)
        Me._localArray = aBandArray

        For ii As Integer = 0 To Me._maxBands - 1
            Select Case ii
                Case 0
                    Me._localArray(ii) = "\BAND1"
                Case 1
                    Me._localArray(ii) = "\BAND2"
                Case 2
                    Me._localArray(ii) = "\BAND3"
                Case 3
                    Me._localArray(ii) = "\BAND4"
                Case 4
                    Me._localArray(ii) = "\BAND5"
                Case 5
                    Me._localArray(ii) = "\SEARCH_AZR"
            End Select
        Next

    End Sub

End Class


text:
<!DOCTYPE html>
<meta charset=utf-8>
<title>invalid junk-noscript-after-source-no-img</title>
<picture><source srcset=x></picture>


text:
void XA_MSGSM_Decoder(unsigned char *ibuf,unsigned short *obuf);
void XA_GSM_Decoder(unsigned char *ibuf,unsigned short *obuf);
void GSM_Init(void);


text:
---
layout: post
title: "Full-Stack Adventure"
date: 2014-12-09T03:00:11-05:00
---

# Section 1: Practical Motivation
It has been a while since my last post. For the past few months, I have been busy helping out the family business.
On a high level, I have been serving as a consultant for the business handling everything from finances, marketing, communication,
technical support and web development.

When my uncle partnered with a local laundry delivery business, this business had a extremely out of date website.
Compelled by curiosity and a do-it-yourself ethic, I decided to create a new and comparatively modern website.
I wrote out this guide to document the experience and to perhaps help other curious minds navigate modern web development.

You can view the finished product [here](http://http://www.usmommy.com/#!/). There is nothing particularly innovative about this web application; it is a simple and modern version of the client's outdated static web page with some dynamic components. I tried to update the text content to be more succinct and concise, however the client insisted on having the content you see now.

# Section 2: Technology Stack
+ [VirtualBox](https://www.virtualbox.org/) to host a guest Linux OS on my Windows 8 laptop.
  *  I highly recommend installing [Guest Additions](https://www.virtualbox.org/manual/ch04.html) and working in seamless mode.
  *  Guest Additions allows for conveniences such as mouse pointer integration, shared folders and shared clipboard between host and guest.

+ [Linux Mint](http://www.linuxmint.com/) is the Linux OS I chose, though any would be fine.
  * There are numerous desktop environments like Cinnamon, MATE, KDE and XFCE.
  * I chose XFCE, the arguably lightweight environment to minimize the resource consumption by VirtualBox.
  * Virtual Box Guest Additions must also be installed on the guest operating system.

+ [MEAN.JS](http://meanjs.org/), an open-source Javascript based full-stack framework.
  * MongoDB: Cross-platform document-oriented NoSQL (not only SQL) database.
  * ExpressJS: Node.js web application framework.
  * AngularJS: Front-end MVC framework.
  * NodeJS: Cross-platform runtime environment for server-side and networking applications.
  * Check the MEAN.js page for resources on each layer of the stack.

+ [DigitalOcean](https://www.digitalocean.com/), simple cloud hosting service for the application.
  * I found "Free Two Months Hosting" coupons on RetailMeNot.

+ [GitHub](https://github.com/) for source control and deployment to the Digital Ocean Droplet™.
  * Read [this](http://nvie.com/posts/a-successful-git-branching-model/) awesome post for a good Git branching practices.
  * I develop locally, push to repository and pull on remote.

+ [NameCheap](https://www.namecheap.com/) is where I purchased the domains.
  * I used two promo codes to lower the yearly price from ~$11 to ~$9.

+ [nginx](http://nginx.org/), pronounced "engine x", is an HTTP and reverse proxy server.
  * Node default listens to port 3000, nginx proxies requests from port 80 to the underlying port 3000.

# Section 3: Getting Started
Each of these tasks can take a few hours to complete, especially if you run into any installation or setup issues. Please take your time and make sure each step is completed before moving on. Google and StackOverflow are great resources for troubleshooting and debugging! The following steps assume the host machine runs Windows. If you are already using a Linux-ish operating system, then please skip to step 4.

1. Install VirtualBox, please refer to the [user manual](http://www.virtualbox.org/manual/) for assistance.
2. Download the .iso of your preferred flavor of Linux. View popular options at [DistroWatch](http://distrowatch.com/dwres.php?resource=major).
3. Install VirtualBox Guest Additions on both the host OS and the guest OS.
4. Install MEAN.JS and its [prerequisites](http://meanjs.org/docs.html#getting-started): Node.js, npm, MongoDB, bower, grunt.
5. [Generate](http://meanjs.org/generator.html) your project directory, which initializes with a sample MEAN stack application.

# Section 4: Preemptive Development Advice
*grep*:

{% highlight bash %}
# front-end content you want to edit, but unsure of file location: grep it
# find any file dependencies in unfamiliar directories: grep it

grep -r "texthere" .
# execute in root project directory
{% endhighlight %}

*spelling*:

If your application passes the linter, but is not functioning, check your variable spelling.

*incremental development*:

Work on this project incrementally. Move on to the next section when you understood the current section. This sounds obvious, however it is definitely worth stating and emphasizing. A web application is not as complicated or daunting when you understand its components.

*version control*:

If you decide to create a web application or any non-trivial application without any version control, then you are a very very brave individual.

# Section 5: The Full-Stack Nitty Gritty
I studied computer science, however that does not mean I formally learned web development. Over the the course of my undergraduate years I did study the fundamental components that comprise basic web development: programming languages, computer architecture, databases, operating systems, networks and security. With that stated, a working knowledge of the Linux environment, HTML and Javascript is necessary for the upcoming sub-sections.

**Halt!** Take your time working through this. Take breaks to digest and understand what is going on.
{: .notice}

# 5A: Setting Up Local Development Environment
Before doing anything, you must start the **mongod** service if it is not already started.
You can check by running any of the following in your Terminal:

{% highlight bash %}
# pROCESS sTATUS
$ ps aux | grep mongod
	--or--
$ /etc/init.d/mongod status
	--or--
$ service mongod status
{% endhighlight %}

For future reference, if you are unfamiliar with any of these Terminal commands, then check the **man** pages.

{% highlight bash %}
$ man ps
{% endhighlight %}

Now, start **mongod**, "the primary daemon process for the MongoDB system" !

{% highlight bash %}
$ mongod
[initandlisten] MongoDB starting : pid=6207 port=27017 dbpath=/data/db 64-bit host=zenbook
[initandlisten] db version v2.6.6
...
[initandlisten] ERROR: Insufficient free space for journal files
[initandlisten] Please make at least 3379MB available in /data/db/journal or use --smallfiles
[initandlisten]
[initandlisten] exception in initAndListen: 15926 Insufficient free space for journals, terminating
...
[initandlisten] dbexit: really exiting now

{% endhighlight %}

If you do not have sufficient free space like in the above example, then do:

{% highlight bash %}
$ mongod --smallfiles
[initandlisten] MongoDB starting : pid=6084 port=27017 dbpath=/data/db 64-bit host=zenbook
[initandlisten] db version v2.6.6
...
[initandlisten] waiting for connections on port 27017
[clientcursormon] mem (MB) res:83 virt:728
[clientcursormon]  mapped (incl journal view):544
[clientcursormon]  connections:0
{% endhighlight %}

Open a *new* Terminal window or tab and execute:

{% highlight bash %}
# grunt is a JS task runner used to automate tasks like linting and minification
# grunt conveniently relaunches the application when it detects any saved file changes
# view gruntfile.js in the root project directory for more information
$ grunt
Running "jshint:all" (jshint) task
>> 56 files lint free.

Running "csslint:all" (csslint) task
>> 2 files lint free.

Running "concurrent:default" (concurrent) task
Running "watch" task
Waiting...
Running "nodemon:dev" (nodemon) task
[nodemon] v1.2.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: app/views/**/*.* gruntfile.js server.js config/**/*.js app/**/*.js
[nodemon] starting `node --debug server.js`
debugger listening on port 5858

 NODE_ENV is not defined! Using default development environment

MEAN.JS application started on port 3000
{% endhighlight %}

You may specify the local development NODE_ENV, however it does use the development environment by default.

{% highlight bash %}
# environments are in /.../config/env
$ export NODE_ENV = development
{% endhighlight %}

Open up a web browser in your Linux environment and go to localhost, port 3000:

{% highlight html %}
http://localhost:3000/
{% endhighlight %}

Spend some time familiarizing yourself with the sample application and please take note of the different *modules* in the application. At the very least create an account, log in, create articles on your account and log out.

# 5B: Front-end, the Web UI Layer
From exploring the sample application, you should have noticed the *core* components of the website like the header, the *user* components like the log-in forms, and the *articles* components for interacting with user articles. The **user interface** of these components are organized by isolated modules. All front-end related files are in **/.../public** and as you can see below:

{% highlight html %}
/public
   /dist
   /lib
   /modules
      /articles
         ...
      /core
         /config	-- AngularJS routing
         /controllers	-- AngularJS controllers
         /css
         /img
         /services	-- AngularJS services
         /tests
         /views		-- html files
         ...
      /users
         ...
      ...
   ...
{% endhighlight %}

To test this setup, go into **/.../views** and edit the homepage with your preferred text editor or IDE.

{% highlight bash %}
$ cd /path/to/your/project/project_name/public/modules/core/views/home.client.view.html
{% endhighlight %}

After you update the static content, save the file and *grunt* will automatically update the application. Please use [Bootstrap](http://getbootstrap.com/) for all of your basic user interface needs.

To achieve more dynamic front-end content, you have AngularJS. If you are unfamiliar with Angular and MVC patterns, then now is a great time to follow [this tutorial](https://docs.angularjs.org/tutorial) from the official AngularJS website. I spent a few hours a day spread across an entire week going through the tutorial and experimenting with different examples before I felt comfortable. Extrapolate the newly learned concepts and apply them to the MEAN.JS structuring.

**Halt!** Take a break to rest your body and mind. Get up from your chair and stretch.
{: .notice}

# 5C: Back-end, the Node.js Server
Node.js is the server for this web application. In order to create an account, log-in and log-out, the user interacts with the server from their client. Creating, reading, updating and deleting articles also requires interacting with the server. Web application users should be able to log-in into their accounts and interact with their articles from any computer; no data is stored locally. All server code is located in **/.../app**.

The MEAN.JS stack uses Express, which is a "minimal and flexible" Node.js web application framework. It, like most Node.js libraries, can be installed with npm. Express simplifies the process of writing server code by abstracting away the tedious and complex parts. For more information, read the super informative post by [Evan Hahn](http://evanhahn.com/understanding-express/). It really helps to understand what Express does as many of the sample and toy Node.js applications I found online heavily used it.

{% highlight html %}
/app
   /controller     -- contains Express application controllers; back-end business logic
   /models         -- contains Mongoose models; this is where you define your back-end models
   /routes         -- contains the Express server routing configuration files
   /tests
   /views
   ...
{% endhighlight %}

You should directly see the articles controller code in the **articles.server.controller.js** file. Any code involving 'mongoose' or 'model' are database related. I am not going to delve into the database aspects beyond stating that Mongoose is a Node.js library for interacting with MongoDB. Anyhow, please spend a few moments to read and understand the the code. I have shared a snippet of the file below.

{% highlight js %}
'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	errorHandler = require('./errors'),
	Article = mongoose.model('Article'),
	_ = require('lodash');

/**
 * Create a article
 */
exports.create = function(req, res) {
	var article = new Article(req.body);
	article.user = req.user;

	article.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(article);
		}
	});
};

/**
 * Show the current article
 */
exports.read = function(req, res) {
	res.jsonp(req.article);
};

/**
 * Update a article
 */
exports.update = function(req, res) {
	var article = req.article;

	article = _.extend(article, req.body);

	article.save(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(article);
		}
	});
};

/**
 * Delete an article
 */
exports.delete = function(req, res) {
	var article = req.article;

	article.remove(function(err) {
		if (err) {
			return res.status(400).send({
				message: errorHandler.getErrorMessage(err)
			});
		} else {
			res.jsonp(article);
		}
	});
};

.......

{% endhighlight %}

I used the articles and user controller code as a basis to write my own logic. Writing my own "business logic" is when I had the most fun in this project. The majority of my enjoyable programming experience has been in writing "back-end" code. I am most comfortable with Java and have working knowledge of C and Python. Finally being able to write basic functions was a great motivation boost.

**Halt!:** Feeling bleary-eyed? Take a break, have a cup of tea and resume this later.
{: .notice}

# 5D: Integration
Integrating the front-end and back-end together produces a dynamic web application. Typically, the client interacts with a server by sending a http request and the server sends a http response. In a MEAN stack, Angular sends http **req**uests to the server and waits for a **res**ponse. Express **routes** the request to the proper **controller** to handle the request.

Diagram illustrating the control flow of a MEAN stack web application.

The following section has a concrete example of integrating the front-end and back-end.

# Section 6: Sample Contact Page with nodemailer 0.7.1

a. Create a contact page: **contact.client.view.html**

{% highlight html %}

Email

	  <form name="contactForm" ng-submit="processForm()" class="simple-form">

		  Name
		  <input type="text" data-ng-model="guest.name" class="form-control"
		  placeholder="Your name here" required>

		  Email Address
		  <input type="email" data-ng-model="guest.email" class="form-control"
		  placeholder="Your email address here" required/>

		  Phone Number
		  <input type="phone" data-ng-model="guest.phone" class="form-control"
		  placeholder="Your phone number here" required/>

		  Inquiry
		  <textarea type="text" data-ng-model="guest.inquiry" class="form-control"
		  rows="5" placeholder="Your message here" required/> </textarea>

		  <button class="btn btn-primary btn-lg">Submit Inquiry</button>

	  </form>

		Thank you, your inquiry has been submitted.

	  <button class="btn btn-success btn-lg" ng-click="sent = !sent">
	  Submit Another Inquiry!
	  </button>

{% endhighlight %}

b. Create ContactController: **contact.client.controller.js**

{% highlight js %}
'use strict';
angular.module('core').controller('ContactController', ['$scope', '$http', '$location',
  function($scope, $http, $location) {

  	// the naming of our data model is consistent
	$scope.guest = {};
	$scope.sent = false;

	// when the user submits it triggers processForm()
	$scope.processForm = function() {

	  // *** IMPORTANT IMPORTANT ***
	  // an http request is posted to the server
	  // *** IMPORTANT IMPORTANT ***

	  $http.post('/sendContact', $scope.guest)
	  .success(function(response) {
		  console.log('Success! :D');

		  //logs to browser console (Chrome F12)

	  }).error(function(response) {
		  console.log(response);
	  });

	  $scope.contactForm.$setPristine();
	  $scope.guest = {};
	  $scope.sent = true;
	};
  }]);
{% endhighlight %}

c.  Route Angular controller to view: update **core.client.routes.js**

{% highlight js %}
'use strict';

// Setting up route
angular.module('core').config(['$stateProvider', '$urlRouterProvider',
  function($stateProvider, $urlRouterProvider) {
	// Redirect to home view when route not found
	$urlRouterProvider.otherwise('/');

	$stateProvider
      .state('home', {
        url: '/',
        templateUrl: 'modules/core/views/home.client.view.html'
      })
      .state('contact',{
        url: '/contact',
        templateUrl: 'modules/core/views/contact.client.view.html'
      });
    }
]);
{% endhighlight %}

d. Add contact page to header: update **header.client.view.html**

{% highlight html %}

        Contact

{% endhighlight %}

e.  Setup Express to route /sendContact request to controller: **core.server.routes.js**

{% highlight js %}
'use strict';

var core = require('../../app/controllers/core');

module.exports = function(app) {

	// Root routing
	app.route('/').get(core.index);

	// Receives /sendContact request and calls the sendContact function
	app.route('/sendContact').post(core.sendContact);

};
{% endhighlight %}

f. Create a function to send a email: **core.server.controller.js**

{% highlight js %}
'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
errorHandler = require('./errors'),
Contact = mongoose.model('Contact'),
nodemailer = require('nodemailer'),
_ = require('lodash');

// you may have you downgrade your version of nodemailer
// MEAN.JS uses a more recent version that is incompatible

exports.index = function(req, res) {
  res.render('index', {
	user: req.user || null
  });
};

// update with your gmail information
// you may have to update your gmail settings
var gmTransport = nodemailer.createTransport('SMTP',{
  service: 'Gmail',
  auth: {
	user: 'your@gmail.address',
	pass: 'yourPassword'
  }
});

exports.sendContact = function(req, res) {

  // logs to grunt task
  console.log('sent inquiry');

  var mailOptions = {
	to : 'site@email.address',
	subject : 'Inquiry from: [' + req.body.name + ']',
	html: req.body.inquiry
  };

  gmTransport.sendMail(mailOptions, function(error, response){
	if(error){
  	  console.log(error);
	}else{
	  console.log('Message sent: ' + response.message);
	}
  });
};

{% endhighlight %}

g. Update (downgrade) the version of nodemailer in **package.json** to 0.7.1.

h. Test this locally by going to localhost and try using the contact form.

# Section 7: Deployment with Digital Ocean
Once you have completed testing locally, then it is time to deploy!

# 7A: Hosting Setup on DigitalOcean
a. Purchase domain (from namecheap).

b. Update "Domain Name Server Setup" and specify custom DNS servers.
![Namecheap Setup](http://i.imgur.com/SccNax1.png)

c. Sign up and log into DigitalOcean.

d. Create a droplet.

		1. Name your droplet.
		2. Select a size (some promotions offer $10 credits).
		3. Select your region.
		4. Select a linux distribution.
		5. Select the MEAN application.

e. Configure DNS on DigitalOcean
![DigitalOcean DNS](http://i.imgur.com/1CsqtJW.png)

f. Wait about 10-15 minutes for the DNS changes to propagate.

g. Ping the new domain.

{% highlight bash %}
$ ping yourdomain.com
PING yourdomain.com (12.34.56.789) 56(84) bytes of data.
64 bytes from 12.34.56.789: icmp_req=1 ttl=63 time=1.47 ms
64 bytes from 12.34.56.789: icmp_req=2 ttl=63 time=0.674 ms
{% endhighlight %}

### 7B: Launching the Droplet (server)

{% highlight bash %}
# 1. SSH into your droplet. Your password is emailed to you.
$ ssh root@111.111.111.111
-- or --
$ ssh root@yourdomain.com

# 2. Assuming you have been using source control, clone your application to the droplet.
$ cd /var/www
$ git clone https://github.com/yourGitHubName/yourProjectRepository

# 3. Set NODE_ENV
$ export NODE_ENV = "production"

# 4. Build your project:
$ grunt build

# 5. Install foreverjs
$ [sudo] npm install forever -g

# 6. Execute forever to keep your application running (even after you exit the droplet).
$ forever start server.js
{% endhighlight %}

# 7C: Reverse Proxy with NGINX
The MEAN.JS application listens to port 3000 by default. When people access **yourdomain.com** they have to append the port making it **yourdomain.com:3000**, which is neither convenient or pleasant looking. By not specifying a port, **yourdomain.com** is actually the same as **yourdomain.com:80**. Whenever the user accesses the web application at **yourdomain.com**, their interactions should be passed from port 80 to port 3000. nginx, an HTTP and reverse proxy server, is exactly what we need to achieve that goal.

{% highlight bash %}
# install nginx
$ sudo apt-get update
$ sudo apt-get install nginx
{% endhighlight %}

The following is the setup I use.

{% highlight bash %}
# this redirects all non-www traffic to www
server {
    server_name  yourdomain.com;
    rewrite ^(.*) http://www.yourdomain.com$1 permanent;
}

# listens for requests to port 80 and passes it to port 3000.
server {

    listen 80;

    server_name www.yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
{% endhighlight %}

If you like my nginx setup you can use it by doing the following:

{% highlight bash %}
$ cd /etc/nginx/sites-available

# replace the content of the "default" file with the above setup.
$ [sudo] vim default
-- or --
$ scp ...

# create a symlink of that file in site-enabled
$ ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

{% endhighlight %}

After configuring nginx, restart it.

{% highlight bash %}
$ /etc/init.d/nginx restart
{% endhighlight %}

Now you should be able to visit **yourdomain.com** from anywhere!

# Section 8: Postmortem
This project was my first official "modern" web application. I previously made a Java servlet application, [YelpMeOut!](https://github.com/Kreispy/YelpMeOut), for a database project (CIS330 with Susan Davidson), but the web components of that project were cursory and not emphasized. This modern web application was initially overwhelming, confusing and difficult. At that point I just installed MEAN.JS and was not sure where or how to begin; I was aimlessly reading the sample project and trying to make sense of it. After getting my bearings, I spent time studying each individual layer of the MEAN stack, which was rather time consuming but overall straightforward. I thought getting each layer to interact with each other was going to be the greatest difficultly, however it was not. Using a full-stack framework allowed me to easily adopt good folder structures and proper routing.

[Recently](https://news.ycombinator.com/item?id=8669557) the core members behind the [Node.js](http://nodejs.org/) framework forked and created [io.js](https://github.com/iojs/io.js). These core members were unhappy with Joyent's overall management of the Node.js project. This is germane because MEAN.JS is a fork of the more popular MEAN.IO. You can read more about that [here](http://stackoverflow.com/questions/23199392/difference-between-mean-js-and-mean-io). In retrospect, I might have been able to complete this application sooner if I went with MEAN.IO. MEAN.IO, being relatively older and more well known, is more documented and supported (currently) than MEAN.JS.

Completing this project has bolstered my confidence in my technical skills and has increased my general technical capabilities. Documenting the project from start to finish has made me more patient and also more appreciative of thorough documentation. Looking forward, there are a few sections of text that I would like to revise in the future (to make more stylistically consistent). I am still trying to determine my style of expository technical writing. It took more than three months worth of my free time to learn both the framework and general web development principles. It took about an additional month or so to digest and document my adventure. Since finishing this post, I started working on a new application in Java with the Play framework. Thank you for taking the time to read this post.


text:
#import "NSMutableAttributedString+FFKit.h"

@implementation NSMutableAttributedString (FFKit)

+ (instancetype) stringWithString: (NSString*) str {
    return [[NSMutableAttributedString alloc] initWithString: str];
}

+ (instancetype) stringWithString: (NSString*) str attributes: (NSDictionary*) attrs {
    return [[NSMutableAttributedString alloc] initWithString: str attributes: attrs];
}

+ (instancetype) stringWithAttributedString: (NSAttributedString*) attrStr {
    return [[NSMutableAttributedString alloc] initWithAttributedString: attrStr];
}

- (void) setFont: (UIFont*) font {
    [self setFont: font range: NSMakeRange (0, [self length])];
}

- (void) setFont: (UIFont*) font range: (NSRange) range {
    [self addAttribute: NSFontAttributeName value: font range: range];
}

- (void) setTextColor: (UIColor*) color {
    [self setTextColor: color range: NSMakeRange (0, [self length])];
}

- (void) setTextColor: (UIColor*) color range: (NSRange) range {
    [self addAttribute: NSForegroundColorAttributeName value: color range: range];
}

- (void) setKerning: (CGFloat) kerning {
    [self setKerning: kerning range: NSMakeRange (0, [self length])];
}

- (void) setKerning: (CGFloat) kerning range: (NSRange) range {
    [self addAttribute: NSKernAttributeName value: @(kerning) range: range];
}

- (void) setParagraphStyle: (NSParagraphStyle*) style {
    [self setParagraphStyle: style range: NSMakeRange (0, [self length])];
}

- (void) setParagraphStyle: (NSParagraphStyle*) style range: (NSRange) range {
    [self addAttribute: NSParagraphStyleAttributeName value: style range: range];
}

@end


text:
package org.jivesoftware.smackx.commands;

import org.jivesoftware.smackx.packet.AdHocCommandData;

/**
 * Represents a command that can be executed locally from a remote location. This
 * class must be extended to implement an specific ad-hoc command. This class
 * provides some useful tools:

 *
Node

 *
Name

 *
Session ID

 *
Current Stage

 *
Available actions

 *
Default action

 *

 * To implement a new command extend this class and implement all the abstract
 * methods. When implementing the actions remember that they could be invoked
 * several times, and that you must use the current stage number to know what to
 * do.
 *
 * @author Gabriel Guardincerri
 */
public abstract class LocalCommand extends AdHocCommand {

    /**
     * The time stamp of first invokation of the command. Used to implement the session timeout.
     */
    private long creationDate;

    /**
     * The unique ID of the execution of the command.
     */
    private String sessionID;

    /**
     * The full JID of the host of the command.
     */
    private String ownerJID;

    /**
     * The number of the current stage.
     */
    private int currenStage;

    public LocalCommand() {
        super();
        this.creationDate = System.currentTimeMillis();
        currenStage = -1;
    }

    /**
     * The sessionID is an unique identifier of an execution request. This is
     * automatically handled and should not be called.
     *
     * @param sessionID the unique session id of this execution
     */
    public void setSessionID(String sessionID) {
        this.sessionID = sessionID;
        getData().setSessionID(sessionID);
    }

    /**
     * Returns the session ID of this execution.
     *
     * @return the unique session id of this execution
     */
    public String getSessionID() {
        return sessionID;
    }

    /**
     * Sets the JID of the command host. This is automatically handled and should
     * not be called.
     *
     * @param ownerJID the JID of the owner.
     */
    public void setOwnerJID(String ownerJID) {
        this.ownerJID = ownerJID;
    }

    @Override
    public String getOwnerJID() {
        return ownerJID;
    }

    /**
     * Returns the date the command was created.
     *
     * @return the date the command was created.
     */
    public long getCreationDate() {
        return creationDate;
    }

    /**
     * Returns true if the current stage is the last one. If it is then the
     * execution of some action will complete the execution of the command.
     * Commands that don't have multiple stages can always return <tt>true</tt>.
     *
     * @return true if the command is in the last stage.
     */
    public abstract boolean isLastStage();

    /**
     * Returns true if the specified requester has permission to execute all the
     * stages of this action. This is checked when the first request is received,
     * if the permission is grant then the requester will be able to execute
     * all the stages of the command. It is not checked again during the
     * execution.
     *
     * @param jid the JID to check permissions on.
     * @return true if the user has permission to execute this action.
     */
    public abstract boolean hasPermission(String jid);

    /**
     * Returns the currently executing stage number. The first stage number is
     * 0. During the execution of the first action this method will answer 0.
     *
     * @return the current stage number.
     */
    public int getCurrentStage() {
        return currenStage;
    }

    @Override
    void setData(AdHocCommandData data) {
        data.setSessionID(sessionID);
        super.setData(data);
    }

    /**
     * Increase the current stage number. This is automatically handled and should
     * not be called.
     *
     */
    void incrementStage() {
        currenStage++;
    }

    /**
     * Decrease the current stage number. This is automatically handled and should
     * not be called.
     *
     */
    void decrementStage() {
        currenStage--;
    }
}


text:
using System;
using System.Threading.Tasks;
using Orleans.Providers.MongoDB.Test.GrainInterfaces;
using Orleans.Runtime;

namespace Orleans.Providers.MongoDB.Test.Grains
{
    public sealed class ReminderGrain : Grain, IReminderGrain
    {
        public async Task RemoveReminder(string reminder)
        {
            var reminderType = await this.GetReminder(reminder);

            await this.UnregisterReminder(reminderType);
        }

        public async Task<IGrainReminder> StartReminder(string reminderName, TimeSpan period)
        {
            var reminder = await this.RegisterOrUpdateReminder(reminderName, period - TimeSpan.FromSeconds(2), period);

            return reminder;
        }

        public Task ReceiveReminder(string reminderName, TickStatus status)
        {
            return Task.CompletedTask;
        }
    }
}


text:
package org.apache.rya.api.persist.utils;

import static com.google.common.base.Preconditions.checkNotNull;

import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
import org.apache.rya.api.domain.RyaStatement;
import org.apache.rya.api.persist.RyaDAO;
import org.apache.rya.api.resolver.RyaToRdfConversions;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.rio.RDFHandler;

/**
 * Wraps Rya DAO queries into a simpler interface that just passes in the
 * statement to query for and a handler for dealing with each statement in the
 * query result. This handles iterating over the query, throwing any exceptions,
 * and closing the query iterator when done. The same wrapper can be re-used
 * for multiple queries.
 */
public class RyaDaoQueryWrapper {
    private final RyaDAO<?> ryaDao;
    private final RdfCloudTripleStoreConfiguration conf;

    /**
     * Creates a new instance of {@link RyaDaoQueryWrapper}.
     * @param ryaDao the {@link RyaDAO}. (not {@code null})
     * @param conf the {@link RdfCloudTripleStoreConfiguration}.
     * (not {@code null})
     */
    public RyaDaoQueryWrapper(final RyaDAO<?> ryaDao, final RdfCloudTripleStoreConfiguration conf) {
        this.ryaDao = checkNotNull(ryaDao);
        this.conf = checkNotNull(conf);
    }

    /**
     * Creates a new instance of {@link RyaDaoQueryWrapper}.
     * @param ryaDao the {@link RyaDAO}. (not {@code null})
     */
    public RyaDaoQueryWrapper(final RyaDAO<?> ryaDao) {
        this(checkNotNull(ryaDao), ryaDao.getConf());
    }

    /**
     * Handles all results of a query. Closes the query iterator when done.
     * @param subject the subject {@link Resource} to query for.
     * @param predicate the predicate {@link IRI} to query for.
     * @param object the object {@link Value} to query for.
     * @param rdfStatementHandler the {@link RDFHandler} to use for handling
     * each statement returned. (not {@code null})
     * @param contexts the context {@link Resource}s to query for.
     * @throws QueryEvaluationException
     */
    public void queryAll(final Resource subject, final IRI predicate, final Value object, final RDFHandler rdfStatementHandler, final Resource... contexts) throws QueryEvaluationException {
        checkNotNull(rdfStatementHandler);
        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDao, subject, predicate, object, conf, contexts);
        try {
            while (iter.hasNext()) {
                final Statement statement = iter.next();
                try {
                    rdfStatementHandler.handleStatement(statement);
                } catch (final Exception e) {
                    throw new QueryEvaluationException("Error handling statement.", e);
                }
            }
        } finally {
            if (iter != null) {
                iter.close();
            }
        }
    }

    /**
     * Handles all results of a query. Closes the query iterator when done.
     * @param statement the {@link Statement} to query for. (not {@code null})
     * @param rdfStatementHandler the {@link RDFHandler} to use for handling
     * each statement returned. (not {@code null})
     * @throws QueryEvaluationException
     */
    public void queryAll(final Statement statement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
        final Resource subject = statement.getSubject();
        final IRI predicate = statement.getPredicate();
        final Value object = statement.getObject();
        final Resource context = statement.getContext();
        queryAll(subject, predicate, object, rdfStatementHandler, context);
    }

    /**
     * Handles all results of a query. Closes the query iterator when done.
     * @param ryaStatement the {@link RyaStatement} to query for.
     * (not {@code null})
     * @param rdfStatementHandler the {@link RDFHandler} to use for handling
     * each statement returned. (not {@code null})
     * @throws QueryEvaluationException
     */
    public void queryAll(final RyaStatement ryaStatement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
        checkNotNull(ryaStatement);
        final Statement statement = RyaToRdfConversions.convertStatement(ryaStatement);
        queryAll(statement, rdfStatementHandler);
    }

    /**
     * Handles only the first result of a query. Closes the query iterator when
     * done.
     * @param subject the subject {@link Resource} to query for.
     * @param predicate the predicate {@link IRI} to query for.
     * @param object the object {@link Value} to query for.
     * @param rdfStatementHandler the {@link RDFHandler} to use for handling the
     * first statement returned. (not {@code null})
     * @param contexts the context {@link Resource}s to query for.
     * @throws QueryEvaluationException
     */
    public void queryFirst(final Resource subject, final IRI predicate, final Value object, final RDFHandler rdfStatementHandler, final Resource... contexts) throws QueryEvaluationException {
        checkNotNull(rdfStatementHandler);
        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDao, subject, predicate, object, conf, contexts);
        try {
            if (iter.hasNext()) {
                final Statement statement = iter.next();
                try {
                    rdfStatementHandler.handleStatement(statement);
                } catch (final Exception e) {
                    throw new QueryEvaluationException("Error handling statement.", e);
                }
            }
        } finally {
            if (iter != null) {
                iter.close();
            }
        }
    }

    /**
     * Handles only the first result of a query. Closes the query iterator when
     * done.
     * @param statement the {@link Statement} to query for. (not {@code null})
     * @param rdfStatementHandler the {@link RDFHandler} to use for handling the
     * first statement returned. (not {@code null})
     * @throws QueryEvaluationException
     */
    public void queryFirst(final Statement statement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
        checkNotNull(statement);
        final Resource subject = statement.getSubject();
        final IRI predicate = statement.getPredicate();
        final Value object = statement.getObject();
        final Resource context = statement.getContext();
        queryFirst(subject, predicate, object, rdfStatementHandler, context);
    }

    /**
     * Handles only the first result of a query. Closes the query iterator when
     * done.
     * @param ryaStatement the {@link RyaStatement} to query for.
     * (not {@code null})
     * @param rdfStatementHandler the {@link RDFHandler} to use for handling the
     * first statement returned. (not {@code null})
     * @throws QueryEvaluationException
     */
    public void queryFirst(final RyaStatement ryaStatement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
        checkNotNull(ryaStatement);
        final Statement statement = RyaToRdfConversions.convertStatement(ryaStatement);
        queryFirst(statement, rdfStatementHandler);
    }
}


text:
"""A simple script to download a full table in CSV form from https://data.epa.gov/efservice"""

import os
import pathlib
import ssl
import sys

import pandas as pd

from absl import app
from absl import flags

# Allows the following module imports to work when running as a script
_SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(_SCRIPT_PATH, '../..'))
from us_epa.util import facilities_helper as fh

FLAGS = flags.FLAGS

flags.DEFINE_string('companies_table_name', '', 'Name of table to download')
flags.DEFINE_string('output_path', 'tmp_data', 'Output directory')

_API_ROOT = 'https://data.epa.gov/efservice/'
_MAX_ROWS = 10000

def main(_):
    assert FLAGS.output_path
    assert FLAGS.companies_table_name
    pathlib.Path(FLAGS.output_path).mkdir(exist_ok=True)
    fh.download(_API_ROOT, FLAGS.companies_table_name, _MAX_ROWS,
                FLAGS.output_path)

if __name__ == '__main__':
    app.run(main)


text:
@interface PodsDummy_Pods_BRCacheManager_BRCacheManager : NSObject
@end
@implementation PodsDummy_Pods_BRCacheManager_BRCacheManager
@end


text:
import { Injector } from 'angular2/di';
import * as avmModule from './view_manager';
import { ElementRef } from './element_ref';
import { ViewRef, ProtoViewRef } from './view_ref';
/**
 * @exportedAs angular2/core
 */
export declare class ViewContainerRef {
    viewManager: avmModule.AppViewManager;
    element: ElementRef;
    constructor(viewManager: avmModule.AppViewManager, element: ElementRef);
    private _getViews();
    clear(): void;
    get(index: number): ViewRef;
    length: number;
    create(protoViewRef?: ProtoViewRef, atIndex?: number, context?: ElementRef, injector?: Injector): ViewRef;
    insert(viewRef: ViewRef, atIndex?: number): ViewRef;
    indexOf(viewRef: ViewRef): number;
    remove(atIndex?: number): void;
    /**
     * The method can be used together with insert to implement a view move, i.e.
     * moving the dom nodes while the directives in the view stay intact.
     */
    detach(atIndex?: number): ViewRef;
}
export declare var __esModule: boolean;


text:
class RedirectsController < ApplicationController
  # GET /redirects
  # GET /redirects.json
  def index
    @redirects = Redirect.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @redirects }
    end
  end

  # GET /redirects/1
  # GET /redirects/1.json
  def show
    @redirect = Redirect.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @redirect }
    end
  end

  # GET /redirects/new
  # GET /redirects/new.json
  def new
    @redirect = Redirect.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @redirect }
    end
  end

  # GET /redirects/1/edit
  def edit
    @redirect = Redirect.find(params[:id])
  end

  # POST /redirects
  # POST /redirects.json
  def create
    @redirect = Redirect.new(params[:redirect])

    respond_to do |format|
      if @redirect.save
        format.html { redirect_to @redirect, notice: 'Redirect was successfully created.' }
        format.json { render json: @redirect, status: :created, location: @redirect }
      else
        format.html { render action: "new" }
        format.json { render json: @redirect.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /redirects/1
  # PUT /redirects/1.json
  def update
    @redirect = Redirect.find(params[:id])

    respond_to do |format|
      if @redirect.update_attributes(params[:redirect])
        format.html { redirect_to @redirect, notice: 'Redirect was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @redirect.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /redirects/1
  # DELETE /redirects/1.json
  def destroy
    @redirect = Redirect.find(params[:id])
    @redirect.destroy

    respond_to do |format|
      format.html { redirect_to redirects_url }
      format.json { head :no_content }
    end
  end
end


text:
'use strict';

/**
 * @ngdoc function
 * @name sitioRealApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the sitioRealApp
 */
angular.module('sitioRealApp')
  .controller('MainCtrl', function () {
    this.awesomeThings = [
      'HTML5 Boilerplate',
      'AngularJS',
      'Karma'
    ];
  });


text:
using Bumblebee.Interfaces;
using Bumblebee.Setup;

namespace Bumblebee.IntegrationTests.Shared.Sessions
{
	public class DerivedSessionWithWrongArgs : Session
	{
		public DerivedSessionWithWrongArgs(IDriverEnvironment environment, IMonkey monkey) : base(environment)
		{
			Monkey = monkey;
		}
	}
}


text:
var request = require('request');
var querystring = require('querystring');
var client = require('./api-client');

var URL_BASE = 'https://ridb.recreation.gov/api/v1/';

// Retrieves all campsites.
exports.getAll = function(params, callback) {
    url = URL_BASE + 'campsites/?' + querystring.stringify(params);
	client.makeApiCall(url, callback);
};

// Retrieves a specific campsite.
exports.getSpecific = function(campsiteID, callback) {
    url = URL_BASE + 'campsites/' + campsiteID;
	client.makeApiCall(url, callback);
};

// Retrieves all campsites for a specific facility.
exports.getAllForFacility = function(facilityID, params, callback) {
    url = URL_BASE + 'facilities/' + facilityID + '/campsites?' + querystring.stringify(params);
	client.makeApiCall(url, callback);
};

// Retrieves a specific campsite for a specific facility.
exports.getSpecific = function(facilityID, campsiteID, callback) {
    url = URL_BASE + 'facilities/' + facilityID + '/campsites/' + campsiteID;
	client.makeApiCall(url, callback);
};

// Retrieves all permitted equipment for a campsite.
exports.getEquipment = function(campsiteID, params, callback) {
    url = URL_BASE + 'campsites/' + campsiteID + '/permittedequipment?' + querystring.stringify(params);
	client.makeApiCall(url, callback);
};

// Retrieves a specific permitted equipment for a specific campsite.
exports.getSpecificEquipment = function(campsiteID, permittedequipmentID, callback) {
    url = URL_BASE + 'campsites/' + campsiteID + '/permittedequipment/' + permittedequipmentID;
	client.makeApiCall(url, allback);
};

// Retrieves all attributes for a specific campsite.
exports.getAttributes = function(campsiteID, params, callback) {
    url = URL_BASE + 'campsites/' + campsiteID + '/attributes?' + querystring.stringify(params);
	client.makeApiCall(url, callback);
};


text:
let listener

const callbackIds = []

export function startCompass (options, callbackId) {
  const {
    invokeCallbackHandler: invoke
  } = UniServiceJSBridge
  if (!window.DeviceOrientationEvent) {
    return {
      errMsg: 'startCompass:fail'
    }
  }
  function addEventListener () {
    listener = function (event) {
      const direction = 360 - event.alpha
      callbackIds.forEach(callbackId => {
        invoke(callbackId, {
          direction: direction || 0
        })
      })
    }
    window.addEventListener('deviceorientation', listener, false)
  }
  if (!listener) {
    if (DeviceOrientationEvent.requestPermission) {
      DeviceOrientationEvent.requestPermission().then((res) => {
        if (res === 'granted') {
          addEventListener()
          invoke(callbackId, {
            errMsg: 'startCompass:ok'
          })
        } else {
          invoke(callbackId, {
            errMsg: `startCompass:fail ${res}`
          })
        }
      }).catch(error => {
        invoke(callbackId, {
          errMsg: `startCompass:fail ${error}`
        })
      })
      return
    }
    addEventListener()
  }
  return {}
}

export function stopCompass () {
  if (listener) {
    window.removeEventListener('deviceorientation', listener, false)
    listener = null
  }
  return {}
}

export function onCompassChange (callbackId) {
  if (!callbackIds.length) {
    startCompass()
  }
  callbackIds.push(callbackId)
}

export function offCompassChange (callbackId) {
  // 暂不支持移除所有监听
  if (callbackId) {
    const index = callbackIds.indexOf(callbackId)
    if (index >= 0) {
      callbackIds.splice(index, 1)
    }
  }
  if (!callbackIds.length) {
    stopCompass()
  }
}


text:
"""
  The tools here allow us to
  (1) translate from XML to Val/Tar/Arr using xmlreader.h
  (2) translate from Val/Tab/Arr to XML using xmldumper.h

  The basic premise of these tools is that you are using
  XML as key-value pairs, and thus translating between
  dictionaries and XML is straight-forward.  In the
  following example, there is an obvious mapping between
  dictionaries and XML:

    <book attr1="1" attr2="2">
       <chapter>text chap 1</chapter>
       <chapter>text chap 2</chapter>
    </book>

  ----------------------------------

   { 'book' = {
         '__attrs__' = { 'attr1':"1", 'attr2':"2" }
         'chapter' = [ 'text chap1', 'text chap2']
   }

  Adding attributes complicates the issues: many of the options
  below help control how the attributes in XML gets translated.
  The examples below showing UNFOLDING (or not) of attributes

  <html>
    <book attr1="1" attr2="2">
      <chapter> chapter 1 </chapter>
      <chapter> chapter 2 </chapter>
    </book>
  </html>
  ----------------------------------------
  { 'html': {
       'book': {
          '_attr1':"1",     <!--- Attributes UNFOLDED -->
          '_attr2':"2",
          'chapter': [ 'chapter1', 'chapter2' ]
       }
  }
   or
  { 'html' : {
       'book': {
          '__attrs__': { 'attr1'="1", 'attr2'="2" },  <!-- DEFAULT way -->
          'chapter' : [ 'chapter1', 'chapter2' ]
       }
    }
  }

  ** Example where XML really is better:
  ** This is more of a "document", where HTML is better (text and
  key-values are interspersed)
  <html>
    <book attr1="1" attr2="2">
      This is the intro
      <chapter> chapter 1 </chapter>
      This is the extro
    </book>
  </html>

  {
    'book': {
       'chapter': { ???
       }
    }
  }

  ???? ['book'] -> "This is the intro" or "This is the outro?"
  NEITHER.  It gets dumped, as book is a dictionary.
  This is an example where converting from XML to Dictionaries
  may be a bad idea and just may not be a good correspondance.

  Options are formed by 'or'ing together.
"""

from xmlloader import *
from xmldumper import *


text:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

	<!-- *********内容管理********* -->
    <bean id="contentService" class="cn.com.newcapec.citycard.content.service.impl.ContentService" parent="baseService"/>
    <bean id="contentAction" class="cn.com.newcapec.citycard.content.action.ContentAction" scope="prototype" parent="commonAction">
        <property name="contentService">
            <ref local="contentService"/>
        </property>
    </bean>

 	<!-- 公告 -->
    <bean id="bulletinAction" class="cn.com.newcapec.citycard.content.action.BulletinAction" scope="prototype" parent="contentAction"/>
</beans>


text:
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(wnwen): Move to chrome.storage.local, wrap calls, add JsDocs.

/**
 * Convert the string to boolean if possible.
 * @return {(boolean|string)} The Boolean value if possible, 'undefined'
 *     otherwise.
 */
function stringToBoolean(str) {
  return (str == 'true') ? true : (str == 'false') ? false : 'undefined';
}

function validBoolean(b) {
  return b == true || b == false;
}

// ======= Delta setting =======

/** @const {number} */ var DEFAULT_DELTA = 0.5;
/** @const {string} */ var LOCAL_STORAGE_TAG_DELTA = 'cvd_delta';
/** @const {string} */ var LOCAL_STORAGE_TAG_SITE_DELTA = 'cvd_site_delta';

function validDelta(delta) {
  return delta >= 0 && delta <= 1;
}

function getDefaultDelta() {
  var delta = localStorage[LOCAL_STORAGE_TAG_DELTA];
  if (validDelta(delta)) {
    return delta;
  }
  delta = DEFAULT_DELTA;
  localStorage[LOCAL_STORAGE_TAG_DELTA] = delta;
  return delta;
}

function setDefaultDelta(delta) {
  if (!validDelta(delta)) {
    delta = DEFAULT_DELTA;
  }
  localStorage[LOCAL_STORAGE_TAG_DELTA] = delta;
}

function getSiteDelta(site) {
  var delta = getDefaultDelta();
  try {
    var siteDeltas = JSON.parse(localStorage[LOCAL_STORAGE_TAG_SITE_DELTA]);
    delta = siteDeltas[site];
    if (!validDelta(delta)) {
      delta = getDefaultDelta();
    }
  } catch (e) {
    delta = getDefaultDelta();
  }
  return delta;
}

function setSiteDelta(site, delta) {
  if (!validDelta(delta)) {
    delta = getDefaultDelta();
  }
  var siteDeltas = {};
  try {
    siteDeltas = JSON.parse(localStorage[LOCAL_STORAGE_TAG_SITE_DELTA]);
  } catch (e) {
    siteDeltas = {};
  }
  siteDeltas[site] = delta;
  localStorage[LOCAL_STORAGE_TAG_SITE_DELTA] = JSON.stringify(siteDeltas);
}

function resetSiteDeltas() {
  var siteDeltas = {};
  localStorage[LOCAL_STORAGE_TAG_SITE_DELTA] = JSON.stringify(siteDeltas);
}

// ======= Severity setting =======

/** @const {number} */ var DEFAULT_SEVERITY = 1.0;
/** @const {string} */ var LOCAL_STORAGE_TAG_SEVERITY = 'cvd_severity';

function validSeverity(severity) {
  return severity >= 0 && severity <= 1;
}

function getDefaultSeverity() {
  var severity = localStorage[LOCAL_STORAGE_TAG_SEVERITY];
  if (validSeverity(severity)) {
    return severity;
  }
  severity = DEFAULT_SEVERITY;
  localStorage[LOCAL_STORAGE_TAG_SEVERITY] = severity;
  return severity;
}

function setDefaultSeverity(severity) {
  if (!validSeverity(severity)) {
    severity = DEFAULT_SEVERITY;
  }
  localStorage[LOCAL_STORAGE_TAG_SEVERITY] = severity;
}

// ======= Type setting =======

/** @const {string} */ var INVALID_TYPE_PLACEHOLDER = '';
/** @const {string} */ var LOCAL_STORAGE_TAG_TYPE = 'cvd_type';

function validType(type) {
  return type === 'PROTANOMALY' ||
      type === 'DEUTERANOMALY' ||
      type === 'TRITANOMALY';
}

function getDefaultType() {
  var type = localStorage[LOCAL_STORAGE_TAG_TYPE];
  if (validType(type)) {
    return type;
  }
}

function setDefaultType(type) {
  if (!validType(type)) {
    type = INVALID_TYPE_PLACEHOLDER;
  }
  localStorage[LOCAL_STORAGE_TAG_TYPE] = type;
}

// ======= Simulate setting =======

/** @const {boolean} */ var DEFAULT_SIMULATE = false;
/** @const {string} */ var LOCAL_STORAGE_TAG_SIMULATE = 'cvd_simulate';

function getDefaultSimulate() {
  var simulate = localStorage[LOCAL_STORAGE_TAG_SIMULATE];

  simulate = stringToBoolean(simulate);

  if (validBoolean(simulate)) {
    return simulate;
  }
  simulate = DEFAULT_SIMULATE;
  localStorage[LOCAL_STORAGE_TAG_SIMULATE] = simulate;
  return simulate;
}

function setDefaultSimulate(simulate) {
  if (!validBoolean(simulate)) {
    simulate = DEFAULT_SIMULATE;
  }
  localStorage[LOCAL_STORAGE_TAG_SIMULATE] = simulate;
}

// ======= Enable setting =======

/** @const {boolean} */ var DEFAULT_ENABLE = false;
/** @const {string} */ var LOCAL_STORAGE_TAG_ENABLE = 'cvd_enable';

function validEnable(enable) {
  return enable == true || enable == false;
}

function getDefaultEnable() {
  var enable = localStorage[LOCAL_STORAGE_TAG_ENABLE];

  enable = stringToBoolean(enable);

  if (validBoolean(enable)) {
    return enable;
  }
  enable = DEFAULT_ENABLE;
  localStorage[LOCAL_STORAGE_TAG_ENABLE] = enable;
  return enable;
}

function setDefaultEnable(enable) {
  if (!validBoolean(enable)) {
    enable = DEFAULT_ENABLE;
  }
  localStorage[LOCAL_STORAGE_TAG_ENABLE] = enable;
}


text:
class ContainsText

  # this is what the matcher is called on.
  # In this case:
  #   foo.should contains(:bars)
  # foo would be passed to the +initialize+
  def initialize(expected)
    @expected = expected
  end

  def matches?(actual)
    @actual = actual
    return actual && actual.include?(@expected)
  end

  def actual_text
    @actual.to_s.length > 1000000 ? @actual[0, 1000] : @actual
  end

  # error message for should
  def failure_message
    "expected #{actual_text} not to contains #{@expected}, but it did't"
  end

  # error message for should_not
  def negative_failure_message
    "expected #{actual_text} not to contains #{@expected}, but it did"
  end

end

# This method is the one you use with should/should_not
def contains_text?(expected)
  ContainsText.new(expected)
end
alias contains? contains_text?


text:
package com.websystique.springbatch;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import org.joda.time.LocalDate;

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
	public LocalDate unmarshal(String v) throws Exception {
		return new LocalDate(v);
	}

	public String marshal(LocalDate v) throws Exception {
		return v.toString();
	}
}


text:
<!DOCTYPE html >

    <link rel="stylesheet" href="demos.css" type="text/css" media="screen" />

    <title>RGraph demo: Line chart with null values</title>

    <meta name="robots" content="noindex,nofollow" />
    <meta name="description" content="A Line chart with null values" />

Line chart with null values

    <canvas id="cvs" width="600" height="250">[No canvas support]</canvas>

    This goes in the documents header:

<script src="RGraph.common.core.js"></script>
<script src="RGraph.line.js"></script>

    Put this where you want the chart to show up:

<canvas id="cvs" width="600" height="250">
    [No canvas support]
</canvas>

    This is the code that generates the chart:

<script>
    new RGraph.Line({
        id: 'cvs',
        data: [1059990.29, 90000.97,508116.23, 54790.12, null,null,null],
        options: {
            gutterLeft: 75,
            backgroundGridAutofitNumvlines: 6,
            tickmarks: 'filledcircle',
            ticksize: 5,
            numxticks: 6,
            labels: ['John','Fred','Lucy','John','Luis','Pete','Kevin'],
            colors: ['#c00', 'pink'],
            linewidth: 2,
            shadow: false,
            scaleZerostart: true
        }
    }).draw();
</script>

        « Back


text:
using System;
using System.Runtime.Serialization;

namespace Ploeh.AutoFixture.Idioms
{
    /// <summary>
    /// Represents an error about an ill-behaved override of the <see cref="Object.GetHashCode()"/>
    /// method.
    /// </summary>
    [Serializable]
    public class GetHashCodeOverrideException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="GetHashCodeOverrideException"/> class.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "GetHashCode", Justification = "Workaround for a bug in CA: https://connect.microsoft.com/VisualStudio/feedback/details/521030/")]
        public GetHashCodeOverrideException()
            : base("The Object.GetHashCode() override is ill-behaved.")
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="GetHashCodeOverrideException"/> class.
        /// </summary>
        /// <param name="message">
        /// The error message that explains the reason for the exception.
        /// </param>
        public GetHashCodeOverrideException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="GetHashCodeOverrideException"/> class.
        /// </summary>
        /// <param name="message">
        /// The error message that explains the reason for the exception.
        /// </param>
        /// <param name="innerException">
        /// The exception that is the cause of the current exception.
        /// </param>
        public GetHashCodeOverrideException(string message, Exception innerException)
            : base(message, innerException)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="GetHashCodeOverrideException"/> class.
        /// </summary>
        /// <param name="info">
        /// The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the
        /// serialized object data about the exception being thrown.
        /// </param>
        /// <param name="context">
        /// The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains
        /// contextual information about the source or destination.
        /// </param>
        protected GetHashCodeOverrideException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }
}


text:
#ifndef __PPNIL_H
#define __PPNIL_H

#include "common/sedna.h"
#include "tr/executor/base/PPBase.h"

class PPNil : public PPIterator
{
private:
    virtual void do_open   ();
    virtual void do_reopen ();
    virtual void do_close  ();
    virtual void do_next   (xqp_tuple &t);
    virtual void do_accept (PPVisitor &v);

    virtual PPIterator* do_copy(dynamic_context *_cxt_);

public:
    PPNil(dynamic_context *_cxt_, operation_info _info_);
    virtual ~PPNil();
};

#endif