Removed unescape/escape functions, switched to new instruction format.
This commit is contained in:
parent
621f369130
commit
f5b44c97ad
@ -145,8 +145,7 @@ typedef struct guac_instruction {
|
||||
int argc;
|
||||
|
||||
/**
|
||||
* Array of all arguments passed to this instruction. Strings
|
||||
* are not already unescaped.
|
||||
* Array of all arguments passed to this instruction.
|
||||
*/
|
||||
char** argv;
|
||||
|
||||
@ -173,27 +172,7 @@ void guac_free_instruction_data(guac_instruction* instruction);
|
||||
void guac_free_instruction(guac_instruction* instruction);
|
||||
|
||||
/**
|
||||
* Escapes the given string as necessary to be passed within
|
||||
* a Guacamole instruction. The returned string must later be
|
||||
* released with a call to free().
|
||||
*
|
||||
* @param str The string to escape.
|
||||
* @return A new escaped string, which must be freed with free().
|
||||
*/
|
||||
char* guac_escape_string(const char* str);
|
||||
|
||||
/**
|
||||
* Unescapes the given string in-place, as an unescaped string
|
||||
* is always the same length or shorter than the original.
|
||||
*
|
||||
* @param str The string to unescape.
|
||||
* @return A pointer to the original string, which is now unescaped.
|
||||
*/
|
||||
char* guac_unescape_string_inplace(char* str);
|
||||
|
||||
/**
|
||||
* Sends an args instruction over the given GUACIO connection. Each
|
||||
* argument name will be automatically escaped for transmission.
|
||||
* Sends an args instruction over the given GUACIO connection.
|
||||
*
|
||||
* @param io The GUACIO connection to use.
|
||||
* @param args The NULL-terminated array of argument names (strings).
|
||||
@ -202,8 +181,7 @@ char* guac_unescape_string_inplace(char* str);
|
||||
int guac_send_args(GUACIO* io, const char** name);
|
||||
|
||||
/**
|
||||
* Sends a name instruction over the given GUACIO connection. The
|
||||
* name given will be automatically escaped for transmission.
|
||||
* Sends a name instruction over the given GUACIO connection.
|
||||
*
|
||||
* @param io The GUACIO connection to use.
|
||||
* @param name The name to send within the name instruction.
|
||||
@ -222,9 +200,7 @@ int guac_send_name(GUACIO* io, const char* name);
|
||||
int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp);
|
||||
|
||||
/**
|
||||
* Sends an error instruction over the given GUACIO connection. The
|
||||
* error description given will be automatically escaped for
|
||||
* transmission.
|
||||
* Sends an error instruction over the given GUACIO connection.
|
||||
*
|
||||
* @param io The GUACIO connection to use.
|
||||
* @param error The description associated with the error.
|
||||
@ -233,8 +209,7 @@ int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp);
|
||||
int guac_send_error(GUACIO* io, const char* error);
|
||||
|
||||
/**
|
||||
* Sends a clipboard instruction over the given GUACIO connection. The
|
||||
* clipboard data given will be automatically escaped for transmission.
|
||||
* Sends a clipboard instruction over the given GUACIO connection.
|
||||
*
|
||||
* @param io The GUACIO connection to use.
|
||||
* @param data The clipboard data to send.
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <winsock2.h>
|
||||
@ -120,30 +121,8 @@ int64_t guac_parse_int(const char* str) {
|
||||
ssize_t guac_write_int(GUACIO* io, int64_t i) {
|
||||
|
||||
char buffer[128];
|
||||
char* ptr = &(buffer[127]);
|
||||
int64_t nonneg;
|
||||
|
||||
/* Obtain non-negative value */
|
||||
if (i < 0) nonneg = -i;
|
||||
else nonneg = i;
|
||||
|
||||
/* Generate numeric string */
|
||||
|
||||
*ptr = 0;
|
||||
|
||||
do {
|
||||
|
||||
ptr--;
|
||||
*ptr = '0' + (nonneg % 10);
|
||||
|
||||
nonneg /= 10;
|
||||
|
||||
} while (nonneg > 0 && ptr >= buffer);
|
||||
|
||||
/* Prepend with dash if negative */
|
||||
if (i < 0 && ptr >= buffer) *(--ptr) = '-';
|
||||
|
||||
return guac_write_string(io, ptr);
|
||||
snprintf(buffer, sizeof(buffer), "%"PRIi64, i);
|
||||
return guac_write_string(io, buffer);
|
||||
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
@ -61,108 +63,20 @@
|
||||
#include "guacio.h"
|
||||
#include "protocol.h"
|
||||
|
||||
char* guac_escape_string(const char* str) {
|
||||
ssize_t __guac_write_length_string(GUACIO* io, const char* str) {
|
||||
|
||||
char* escaped;
|
||||
char* current;
|
||||
|
||||
int i;
|
||||
int length = 0;
|
||||
|
||||
/* Determine length */
|
||||
for (i=0; str[i] != '\0'; i++) {
|
||||
switch (str[i]) {
|
||||
|
||||
case ';':
|
||||
case ',':
|
||||
case '\\':
|
||||
length += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
length++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate new */
|
||||
escaped = malloc(length+1);
|
||||
|
||||
current = escaped;
|
||||
for (i=0; str[i] != '\0'; i++) {
|
||||
switch (str[i]) {
|
||||
|
||||
case ';':
|
||||
*(current++) = '\\';
|
||||
*(current++) = 's';
|
||||
break;
|
||||
|
||||
case ',':
|
||||
*(current++) = '\\';
|
||||
*(current++) = 'c';
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
*(current++) = '\\';
|
||||
*(current++) = '\\';
|
||||
break;
|
||||
|
||||
default:
|
||||
*(current++) = str[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*current = '\0';
|
||||
|
||||
return escaped;
|
||||
return
|
||||
guac_write_int(io, strlen(str))
|
||||
|| guac_write_string(io, ".")
|
||||
|| guac_write_string(io, str);
|
||||
|
||||
}
|
||||
|
||||
char* guac_unescape_string_inplace(char* str) {
|
||||
ssize_t __guac_write_length_int(GUACIO* io, int64_t i) {
|
||||
|
||||
char* from;
|
||||
char* to;
|
||||
|
||||
from = to = str;
|
||||
for (;;) {
|
||||
|
||||
char c = *(from++);
|
||||
|
||||
if (c == '\\') {
|
||||
|
||||
c = *(from++);
|
||||
if (c == 's')
|
||||
*(to++) = ';';
|
||||
|
||||
else if (c == 'c')
|
||||
*(to++) = ',';
|
||||
|
||||
else if (c == '\\')
|
||||
*(to++) = '\\';
|
||||
|
||||
else if (c == '\0') {
|
||||
*(to++) = '\\';
|
||||
break;
|
||||
}
|
||||
|
||||
else {
|
||||
*(to++) = '\\';
|
||||
*(to++) = c;
|
||||
}
|
||||
}
|
||||
|
||||
else if (c == '\0')
|
||||
break;
|
||||
|
||||
else
|
||||
*(to++) = c;
|
||||
|
||||
}
|
||||
|
||||
*to = '\0';
|
||||
|
||||
return str;
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%"PRIi64, i);
|
||||
return __guac_write_length_string(io, buffer);
|
||||
|
||||
}
|
||||
|
||||
@ -170,27 +84,15 @@ int guac_send_args(GUACIO* io, const char** args) {
|
||||
|
||||
int i;
|
||||
|
||||
/* Handle protocols with no args */
|
||||
if (args[0] == NULL)
|
||||
return guac_write_string(io, "args;");
|
||||
|
||||
if (guac_write_string(io, "args:")) return -1;
|
||||
if (guac_write_string(io, "4.args")) return -1;
|
||||
|
||||
for (i=0; args[i] != NULL; i++) {
|
||||
|
||||
char* escaped;
|
||||
|
||||
if (i > 0) {
|
||||
if (guac_write_string(io, ","))
|
||||
return -1;
|
||||
}
|
||||
|
||||
escaped = guac_escape_string(args[i]);
|
||||
if (guac_write_string(io, escaped)) {
|
||||
free(escaped);
|
||||
if (__guac_write_length_string(io, args[i]))
|
||||
return -1;
|
||||
}
|
||||
free(escaped);
|
||||
|
||||
}
|
||||
|
||||
@ -200,74 +102,46 @@ int guac_send_args(GUACIO* io, const char** args) {
|
||||
|
||||
int guac_send_name(GUACIO* io, const char* name) {
|
||||
|
||||
char* escaped = guac_escape_string(name);
|
||||
|
||||
if (
|
||||
guac_write_string(io, "name:")
|
||||
|| guac_write_string(io, escaped)
|
||||
|| guac_write_string(io, ";")
|
||||
) {
|
||||
free(escaped);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(escaped);
|
||||
return 0;
|
||||
return
|
||||
guac_write_string(io, "4.name,")
|
||||
|| __guac_write_length_string(io, name)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
|
||||
int guac_send_size(GUACIO* io, int w, int h) {
|
||||
|
||||
return
|
||||
guac_write_string(io, "size:")
|
||||
|| guac_write_int(io, w)
|
||||
guac_write_string(io, "4.size,")
|
||||
|| __guac_write_length_int(io, w)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, h)
|
||||
|| __guac_write_length_int(io, h)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
|
||||
int guac_send_clipboard(GUACIO* io, const char* data) {
|
||||
|
||||
char* escaped = guac_escape_string(data);
|
||||
|
||||
if (
|
||||
guac_write_string(io, "clipboard:")
|
||||
|| guac_write_string(io, escaped)
|
||||
|| guac_write_string(io, ";")
|
||||
) {
|
||||
free(escaped);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(escaped);
|
||||
return 0;
|
||||
return
|
||||
guac_write_string(io, "9.clipboard,")
|
||||
|| __guac_write_length_string(io, data)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
|
||||
int guac_send_error(GUACIO* io, const char* error) {
|
||||
|
||||
char* escaped = guac_escape_string(error);
|
||||
|
||||
if (
|
||||
guac_write_string(io, "error:")
|
||||
|| guac_write_string(io, escaped)
|
||||
|| guac_write_string(io, ";")
|
||||
) {
|
||||
free(escaped);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(escaped);
|
||||
return 0;
|
||||
|
||||
return
|
||||
guac_write_string(io, "5.error,")
|
||||
|| __guac_write_length_string(io, error)
|
||||
|| guac_write_string(io, ";");
|
||||
}
|
||||
|
||||
int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) {
|
||||
|
||||
return
|
||||
guac_write_string(io, "sync:")
|
||||
|| guac_write_int(io, timestamp)
|
||||
guac_write_string(io, "4.sync,")
|
||||
|| __guac_write_length_int(io, timestamp)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
@ -277,24 +151,24 @@ int guac_send_copy(GUACIO* io,
|
||||
guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) {
|
||||
|
||||
return
|
||||
guac_write_string(io, "copy:")
|
||||
|| guac_write_int(io, srcl->index)
|
||||
guac_write_string(io, "4.copy,")
|
||||
|| __guac_write_length_int(io, srcl->index)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, srcx)
|
||||
|| __guac_write_length_int(io, srcx)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, srcy)
|
||||
|| __guac_write_length_int(io, srcy)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, w)
|
||||
|| __guac_write_length_int(io, w)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, h)
|
||||
|| __guac_write_length_int(io, h)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, mode)
|
||||
|| __guac_write_length_int(io, mode)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, dstl->index)
|
||||
|| __guac_write_length_int(io, dstl->index)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, dstx)
|
||||
|| __guac_write_length_int(io, dstx)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, dsty)
|
||||
|| __guac_write_length_int(io, dsty)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
@ -305,26 +179,26 @@ int guac_send_rect(GUACIO* io,
|
||||
int r, int g, int b, int a) {
|
||||
|
||||
return
|
||||
guac_write_string(io, "rect:")
|
||||
|| guac_write_int(io, mode)
|
||||
guac_write_string(io, "4,rect,")
|
||||
|| __guac_write_length_int(io, mode)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, layer->index)
|
||||
|| __guac_write_length_int(io, layer->index)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, x)
|
||||
|| __guac_write_length_int(io, x)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, y)
|
||||
|| __guac_write_length_int(io, y)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, width)
|
||||
|| __guac_write_length_int(io, width)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, height)
|
||||
|| __guac_write_length_int(io, height)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, r)
|
||||
|| __guac_write_length_int(io, r)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, g)
|
||||
|| __guac_write_length_int(io, g)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, b)
|
||||
|| __guac_write_length_int(io, b)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, a)
|
||||
|| __guac_write_length_int(io, a)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
@ -333,94 +207,120 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer,
|
||||
int x, int y, int width, int height) {
|
||||
|
||||
return
|
||||
guac_write_string(io, "clip:")
|
||||
|| guac_write_int(io, layer->index)
|
||||
guac_write_string(io, "4.clip,")
|
||||
|| __guac_write_length_int(io, layer->index)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, x)
|
||||
|| __guac_write_length_int(io, x)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, y)
|
||||
|| __guac_write_length_int(io, y)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, width)
|
||||
|| __guac_write_length_int(io, width)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, height)
|
||||
|| __guac_write_length_int(io, height)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
|
||||
typedef struct __guac_write_png_data {
|
||||
|
||||
GUACIO* io;
|
||||
|
||||
char* buffer;
|
||||
int buffer_size;
|
||||
int data_size;
|
||||
|
||||
} __guac_write_png_data;
|
||||
|
||||
cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsigned int length) {
|
||||
|
||||
GUACIO* io = (GUACIO*) closure;
|
||||
__guac_write_png_data* png_data = (__guac_write_png_data*) closure;
|
||||
|
||||
if (guac_write_base64(io, data, length) < 0)
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
/* Calculate next buffer size */
|
||||
int next_size = png_data->data_size + length;
|
||||
|
||||
/* If need resizing, double buffer size until big enough */
|
||||
if (next_size > png_data->buffer_size) {
|
||||
|
||||
char* new_buffer;
|
||||
|
||||
do {
|
||||
png_data->buffer_size <<= 1;
|
||||
} while (next_size > png_data->buffer_size);
|
||||
|
||||
/* Resize buffer */
|
||||
new_buffer = realloc(png_data->buffer, png_data->buffer_size);
|
||||
png_data->buffer = new_buffer;
|
||||
|
||||
}
|
||||
|
||||
/* Append data to buffer */
|
||||
memcpy(png_data->buffer + png_data->data_size, data, length);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
int guac_send_png(GUACIO* io, guac_composite_mode_t mode,
|
||||
const guac_layer* layer, int x, int y, cairo_surface_t* surface) {
|
||||
int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) {
|
||||
|
||||
/* Write instruction and args */
|
||||
|
||||
if (
|
||||
guac_write_string(io, "png:")
|
||||
|| guac_write_int(io, mode)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, layer->index)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, x)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, y)
|
||||
|| guac_write_string(io, ",")
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
__guac_write_png_data png_data;
|
||||
int base64_length;
|
||||
|
||||
/* Write surface */
|
||||
|
||||
if (cairo_surface_write_to_png_stream(surface, __guac_write_png, io) != CAIRO_STATUS_SUCCESS) {
|
||||
png_data.io = io;
|
||||
png_data.buffer_size = 8192;
|
||||
png_data.buffer = malloc(png_data.buffer_size);
|
||||
png_data.data_size = 0;
|
||||
|
||||
if (cairo_surface_write_to_png_stream(surface, __guac_write_png, &png_data) != CAIRO_STATUS_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (guac_flush_base64(io) < 0) {
|
||||
base64_length = (png_data.data_size + 2) / 3 * 4;
|
||||
|
||||
/* Write instruction and args */
|
||||
if (
|
||||
guac_write_int(io, base64_length)
|
||||
|| guac_write_string(io, ".")
|
||||
|| guac_write_base64(io, png_data.buffer, png_data.data_size)
|
||||
|| guac_flush_base64(io))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Finish instruction */
|
||||
free(png_data.buffer);
|
||||
return 0;
|
||||
|
||||
return guac_write_string(io, ";");
|
||||
}
|
||||
|
||||
|
||||
int guac_send_png(GUACIO* io, guac_composite_mode_t mode,
|
||||
const guac_layer* layer, int x, int y, cairo_surface_t* surface) {
|
||||
|
||||
return
|
||||
guac_write_string(io, "3.png,")
|
||||
|| __guac_write_length_int(io, mode)
|
||||
|| guac_write_string(io, ",")
|
||||
|| __guac_write_length_int(io, layer->index)
|
||||
|| guac_write_string(io, ",")
|
||||
|| __guac_write_length_int(io, x)
|
||||
|| guac_write_string(io, ",")
|
||||
|| __guac_write_length_int(io, y)
|
||||
|| guac_write_string(io, ",")
|
||||
|| __guac_write_length_png(io, surface)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
|
||||
|
||||
int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) {
|
||||
|
||||
/* Write instruction and args */
|
||||
|
||||
if (
|
||||
guac_write_string(io, "cursor:")
|
||||
|| guac_write_int(io, x)
|
||||
return
|
||||
guac_write_string(io, "6.cursor,")
|
||||
|| __guac_write_length_int(io, x)
|
||||
|| guac_write_string(io, ",")
|
||||
|| guac_write_int(io, y)
|
||||
|| __guac_write_length_int(io, y)
|
||||
|| guac_write_string(io, ",")
|
||||
) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write surface */
|
||||
|
||||
if (cairo_surface_write_to_png_stream(surface, __guac_write_png, io) != CAIRO_STATUS_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (guac_flush_base64(io) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Finish instruction */
|
||||
|
||||
return guac_write_string(io, ";");
|
||||
|| __guac_write_length_png(io, surface)
|
||||
|| guac_write_string(io, ";");
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user