clipboard.c (4834B)
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#include "common/clipboard.h" 22 23#include <guacamole/client.h> 24#include <guacamole/mem.h> 25#include <guacamole/protocol.h> 26#include <guacamole/stream.h> 27#include <guacamole/string.h> 28#include <guacamole/user.h> 29#include <pthread.h> 30#include <string.h> 31#include <stdlib.h> 32 33guac_common_clipboard* guac_common_clipboard_alloc() { 34 35 guac_common_clipboard* clipboard = guac_mem_alloc(sizeof(guac_common_clipboard)); 36 37 /* Init clipboard */ 38 clipboard->mimetype[0] = '\0'; 39 clipboard->buffer = guac_mem_alloc(GUAC_COMMON_CLIPBOARD_MAX_LENGTH); 40 clipboard->available = GUAC_COMMON_CLIPBOARD_MAX_LENGTH; 41 clipboard->length = 0; 42 43 pthread_mutex_init(&(clipboard->lock), NULL); 44 45 return clipboard; 46 47} 48 49void guac_common_clipboard_free(guac_common_clipboard* clipboard) { 50 51 /* Destroy lock */ 52 pthread_mutex_destroy(&(clipboard->lock)); 53 54 /* Free buffer */ 55 guac_mem_free(clipboard->buffer); 56 57 /* Free base structure */ 58 guac_mem_free(clipboard); 59 60} 61 62/** 63 * Callback for guac_client_foreach_user() which sends clipboard data to each 64 * connected client. 65 * 66 * @param user 67 * The user to send the clipboard data to. 68 * 69 * @param 70 * A pointer to the guac_common_clipboard structure containing the 71 * clipboard data that should be sent to the given user. 72 * 73 * @return 74 * Always NULL. 75 */ 76static void* __send_user_clipboard(guac_user* user, void* data) { 77 78 guac_common_clipboard* clipboard = (guac_common_clipboard*) data; 79 80 char* current = clipboard->buffer; 81 int remaining = clipboard->length; 82 83 /* Begin stream */ 84 guac_stream* stream = guac_user_alloc_stream(user); 85 guac_protocol_send_clipboard(user->socket, stream, clipboard->mimetype); 86 87 guac_user_log(user, GUAC_LOG_DEBUG, 88 "Created stream %i for %s clipboard data.", 89 stream->index, clipboard->mimetype); 90 91 /* Split clipboard into chunks */ 92 while (remaining > 0) { 93 94 /* Calculate size of next block */ 95 int block_size = GUAC_COMMON_CLIPBOARD_BLOCK_SIZE; 96 if (remaining < block_size) 97 block_size = remaining; 98 99 /* Send block */ 100 guac_protocol_send_blob(user->socket, stream, current, block_size); 101 guac_user_log(user, GUAC_LOG_DEBUG, 102 "Sent %i bytes of clipboard data on stream %i.", 103 block_size, stream->index); 104 105 /* Next block */ 106 remaining -= block_size; 107 current += block_size; 108 109 } 110 111 guac_user_log(user, GUAC_LOG_DEBUG, 112 "Clipboard stream %i complete.", 113 stream->index); 114 115 /* End stream */ 116 guac_protocol_send_end(user->socket, stream); 117 guac_user_free_stream(user, stream); 118 119 return NULL; 120 121} 122 123void guac_common_clipboard_send(guac_common_clipboard* clipboard, guac_client* client) { 124 125 pthread_mutex_lock(&(clipboard->lock)); 126 127 guac_client_log(client, GUAC_LOG_DEBUG, "Broadcasting clipboard to all connected users."); 128 guac_client_foreach_user(client, __send_user_clipboard, clipboard); 129 guac_client_log(client, GUAC_LOG_DEBUG, "Broadcast of clipboard complete."); 130 131 pthread_mutex_unlock(&(clipboard->lock)); 132 133} 134 135void guac_common_clipboard_reset(guac_common_clipboard* clipboard, 136 const char* mimetype) { 137 138 pthread_mutex_lock(&(clipboard->lock)); 139 140 /* Clear clipboard contents */ 141 clipboard->length = 0; 142 143 /* Assign given mimetype */ 144 guac_strlcpy(clipboard->mimetype, mimetype, sizeof(clipboard->mimetype)); 145 146 pthread_mutex_unlock(&(clipboard->lock)); 147 148} 149 150void guac_common_clipboard_append(guac_common_clipboard* clipboard, const char* data, int length) { 151 152 pthread_mutex_lock(&(clipboard->lock)); 153 154 /* Truncate data to available length */ 155 int remaining = clipboard->available - clipboard->length; 156 if (remaining < length) 157 length = remaining; 158 159 /* Append to buffer */ 160 memcpy(clipboard->buffer + clipboard->length, data, length); 161 162 /* Update length */ 163 clipboard->length += length; 164 165 pthread_mutex_unlock(&(clipboard->lock)); 166 167} 168