cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

json.c (5251B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "config.h"
     21
     22#include "common/json.h"
     23
     24#include <assert.h>
     25#include <stdlib.h>
     26#include <string.h>
     27
     28#include <guacamole/protocol.h>
     29#include <guacamole/socket.h>
     30#include <guacamole/stream.h>
     31#include <guacamole/user.h>
     32
     33void guac_common_json_flush(guac_user* user, guac_stream* stream,
     34        guac_common_json_state* json_state) {
     35
     36    /* If JSON buffer is non-empty, write contents to blob and reset */
     37    if (json_state->size > 0) {
     38        guac_protocol_send_blob(user->socket, stream,
     39                json_state->buffer, json_state->size);
     40
     41        /* Reset JSON buffer size */
     42        json_state->size = 0;
     43
     44    }
     45
     46}
     47
     48int guac_common_json_write(guac_user* user, guac_stream* stream,
     49        guac_common_json_state* json_state, const char* buffer, int length) {
     50
     51    int blob_written = 0;
     52
     53    /*
     54     * Append to and flush the JSON buffer as necessary to write the given
     55     * data
     56     */
     57    while (length > 0) {
     58
     59        /* Ensure provided data does not exceed size of buffer */
     60        int blob_length = length;
     61        if (blob_length > sizeof(json_state->buffer))
     62            blob_length = sizeof(json_state->buffer);
     63
     64        /* Flush if more room is needed */
     65        if (json_state->size + blob_length > sizeof(json_state->buffer)) {
     66            guac_common_json_flush(user, stream, json_state);
     67            blob_written = 1;
     68        }
     69
     70        /* Append data to JSON buffer */
     71        memcpy(json_state->buffer + json_state->size,
     72                buffer, blob_length);
     73
     74        json_state->size += blob_length;
     75
     76        /* Advance to next blob of data */
     77        buffer += blob_length;
     78        length -= blob_length;
     79
     80    }
     81
     82    return blob_written;
     83
     84}
     85
     86int guac_common_json_write_string(guac_user* user,
     87        guac_stream* stream, guac_common_json_state* json_state,
     88        const char* str) {
     89
     90    int blob_written = 0;
     91
     92    /* Write starting quote */
     93    blob_written |= guac_common_json_write(user, stream,
     94            json_state, "\"", 1);
     95
     96    /* Write given string, escaping as necessary */
     97    const char* current = str;
     98    for (; *current != '\0'; current++) {
     99
    100        /* Escape all quotes and back-slashes */
    101        if (*current == '"' || *current == '\\') {
    102
    103            /* Write any string content up to current character */
    104            if (current != str)
    105                blob_written |= guac_common_json_write(user, stream,
    106                        json_state, str, current - str);
    107
    108            /* Escape the character that was just read */
    109            blob_written |= guac_common_json_write(user, stream,
    110                    json_state, "\\", 1);
    111
    112            /* Reset string */
    113            str = current;
    114
    115        }
    116
    117    }
    118
    119    /* Write any remaining string content */
    120    if (current != str)
    121        blob_written |= guac_common_json_write(user, stream,
    122                json_state, str, current - str);
    123
    124    /* Write ending quote */
    125    blob_written |= guac_common_json_write(user, stream,
    126            json_state, "\"", 1);
    127
    128    return blob_written;
    129
    130}
    131
    132int guac_common_json_write_property(guac_user* user, guac_stream* stream,
    133        guac_common_json_state* json_state, const char* name,
    134        const char* value) {
    135
    136    int blob_written = 0;
    137
    138    /* Write leading comma if not first property */
    139    if (json_state->properties_written != 0)
    140        blob_written |= guac_common_json_write(user, stream,
    141                json_state, ",", 1);
    142
    143    /* Write property name */
    144    blob_written |= guac_common_json_write_string(user, stream,
    145            json_state, name);
    146
    147    /* Separate name from value with colon */
    148    blob_written |= guac_common_json_write(user, stream,
    149            json_state, ":", 1);
    150
    151    /* Write property value */
    152    blob_written |= guac_common_json_write_string(user, stream,
    153            json_state, value);
    154
    155    json_state->properties_written++;
    156
    157    return blob_written;
    158
    159}
    160
    161void guac_common_json_begin_object(guac_user* user, guac_stream* stream,
    162        guac_common_json_state* json_state) {
    163
    164    /* Init JSON state */
    165    json_state->size = 0;
    166    json_state->properties_written = 0;
    167
    168    /* Write leading brace - no blob can possibly be written by this */
    169    assert(!guac_common_json_write(user, stream, json_state, "{", 1));
    170
    171}
    172
    173int guac_common_json_end_object(guac_user* user, guac_stream* stream,
    174        guac_common_json_state* json_state) {
    175
    176    /* Write final brace of JSON object */
    177    return guac_common_json_write(user, stream, json_state, "}", 1);
    178
    179}
    180