/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #include "config.h" #include "common/json.h" #include #include #include #include #include #include #include void guac_common_json_flush(guac_user* user, guac_stream* stream, guac_common_json_state* json_state) { /* If JSON buffer is non-empty, write contents to blob and reset */ if (json_state->size > 0) { guac_protocol_send_blob(user->socket, stream, json_state->buffer, json_state->size); /* Reset JSON buffer size */ json_state->size = 0; } } int guac_common_json_write(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* buffer, int length) { int blob_written = 0; /* * Append to and flush the JSON buffer as necessary to write the given * data */ while (length > 0) { /* Ensure provided data does not exceed size of buffer */ int blob_length = length; if (blob_length > sizeof(json_state->buffer)) blob_length = sizeof(json_state->buffer); /* Flush if more room is needed */ if (json_state->size + blob_length > sizeof(json_state->buffer)) { guac_common_json_flush(user, stream, json_state); blob_written = 1; } /* Append data to JSON buffer */ memcpy(json_state->buffer + json_state->size, buffer, blob_length); json_state->size += blob_length; /* Advance to next blob of data */ buffer += blob_length; length -= blob_length; } return blob_written; } int guac_common_json_write_string(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* str) { int blob_written = 0; /* Write starting quote */ blob_written |= guac_common_json_write(user, stream, json_state, "\"", 1); /* Write given string, escaping as necessary */ const char* current = str; for (; *current != '\0'; current++) { /* Escape all quotes */ if (*current == '"') { /* Write any string content up to current character */ if (current != str) blob_written |= guac_common_json_write(user, stream, json_state, str, current - str); /* Escape the quote that was just read */ blob_written |= guac_common_json_write(user, stream, json_state, "\\", 1); /* Reset string */ str = current; } } /* Write any remaining string content */ if (current != str) blob_written |= guac_common_json_write(user, stream, json_state, str, current - str); /* Write ending quote */ blob_written |= guac_common_json_write(user, stream, json_state, "\"", 1); return blob_written; } int guac_common_json_write_property(guac_user* user, guac_stream* stream, guac_common_json_state* json_state, const char* name, const char* value) { int blob_written = 0; /* Write leading comma if not first property */ if (json_state->properties_written != 0) blob_written |= guac_common_json_write(user, stream, json_state, ",", 1); /* Write property name */ blob_written |= guac_common_json_write_string(user, stream, json_state, name); /* Separate name from value with colon */ blob_written |= guac_common_json_write(user, stream, json_state, ":", 1); /* Write property value */ blob_written |= guac_common_json_write_string(user, stream, json_state, value); json_state->properties_written++; return blob_written; } void guac_common_json_begin_object(guac_user* user, guac_stream* stream, guac_common_json_state* json_state) { /* Init JSON state */ json_state->size = 0; json_state->properties_written = 0; /* Write leading brace - no blob can possibly be written by this */ assert(!guac_common_json_write(user, stream, json_state, "{", 1)); } int guac_common_json_end_object(guac_user* user, guac_stream* stream, guac_common_json_state* json_state) { /* Write final brace of JSON object */ return guac_common_json_write(user, stream, json_state, "}", 1); }