vfs: check userland buffers before reading them.
[haiku.git] / src / servers / registrar / ClipboardHandler.cpp
blob52f8defc7c6bc61dc288976a0324a30b205f13dd
1 /*
2 * Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ingo Weinhold, bonefish@users.sf.net
7 * Gabe Yoder
8 */
11 #include "Clipboard.h"
12 #include "ClipboardHandler.h"
14 #include <Message.h>
15 #include <RegistrarDefs.h>
17 #include <map>
18 #include <string>
21 using std::map;
22 using std::string;
23 using namespace BPrivate;
26 /*!
27 \class ClipboardHandler
28 \brief Handles all clipboard related requests.
31 struct ClipboardHandler::ClipboardMap : map<string, Clipboard*> {};
34 // constructor
35 /*! \brief Creates and initializes a ClipboardHandler.
37 ClipboardHandler::ClipboardHandler()
38 : BHandler(),
39 fClipboards(new ClipboardMap)
44 // destructor
45 /*! \brief Frees all resources associate with this object.
47 ClipboardHandler::~ClipboardHandler()
49 for (ClipboardMap::iterator it = fClipboards->begin();
50 it != fClipboards->end();
51 ++it)
52 delete it->second;
56 // MessageReceived
57 /*! \brief Overrides the super class version to handle the clipboard specific
58 messages.
59 \param message The message to be handled
61 void
62 ClipboardHandler::MessageReceived(BMessage *message)
64 const char *name;
65 BMessage reply;
66 switch (message->what) {
67 case B_REG_ADD_CLIPBOARD:
69 status_t result = B_BAD_VALUE;
71 if (message->FindString("name", &name) == B_OK) {
72 if (_GetClipboard(name))
73 result = B_OK;
76 reply.what = B_REG_RESULT;
77 reply.AddInt32("result", result);
78 message->SendReply(&reply);
79 break;
82 case B_REG_GET_CLIPBOARD_COUNT:
84 status_t result = B_BAD_VALUE;
86 if (message->FindString("name", &name) == B_OK) {
87 if (Clipboard *clipboard = _GetClipboard(name)) {
88 reply.AddInt32("count", clipboard->Count());
89 result = B_OK;
93 reply.AddInt32("result", result);
94 reply.what = B_REG_RESULT;
95 message->SendReply(&reply);
96 break;
99 case B_REG_CLIPBOARD_START_WATCHING:
101 status_t result = B_BAD_VALUE;
103 BMessenger target;
104 if (message->FindString("name", &name) == B_OK
105 && message->FindMessenger("target", &target) == B_OK) {
106 Clipboard *clipboard = _GetClipboard(name);
107 if (clipboard && clipboard->AddWatcher(target))
108 result = B_OK;
111 reply.what = B_REG_RESULT;
112 reply.AddInt32("result", result);
113 message->SendReply(&reply);
114 break;
117 case B_REG_CLIPBOARD_STOP_WATCHING:
119 status_t result = B_BAD_VALUE;
121 BMessenger target;
122 if (message->FindString("name", &name) == B_OK
123 && message->FindMessenger("target", &target) == B_OK) {
124 Clipboard *clipboard = _GetClipboard(name);
125 if (clipboard && clipboard->RemoveWatcher(target))
126 result = B_OK;
129 reply.what = B_REG_RESULT;
130 reply.AddInt32("result", result);
131 message->SendReply(&reply);
132 break;
135 case B_REG_DOWNLOAD_CLIPBOARD:
137 status_t result = B_BAD_VALUE;
139 if (message->FindString("name", &name) == B_OK) {
140 Clipboard *clipboard = _GetClipboard(name);
141 if (clipboard) {
142 reply.AddMessage("data", clipboard->Data());
143 reply.AddMessenger("data source", clipboard->DataSource());
144 reply.AddInt32("count", clipboard->Count());
145 result = B_OK;
149 reply.what = B_REG_RESULT;
150 reply.AddInt32("result", result);
151 message->SendReply(&reply);
152 break;
155 case B_REG_UPLOAD_CLIPBOARD:
157 status_t result = B_BAD_VALUE;
159 BMessage data;
160 BMessenger source;
161 if (message->FindString("name", &name) == B_OK
162 && message->FindMessenger("data source", &source) == B_OK
163 && message->FindMessage("data", &data) == B_OK) {
164 Clipboard *clipboard = _GetClipboard(name);
165 if (clipboard) {
166 int32 localCount;
167 bool failIfChanged;
168 if (message->FindInt32("count", &localCount) == B_OK
169 && message->FindBool("fail if changed", &failIfChanged)
170 == B_OK
171 && failIfChanged
172 && localCount != clipboard->Count()) {
173 // atomic support
174 result = B_ERROR;
175 } else {
176 clipboard->SetData(&data, source);
177 result = reply.AddInt32("count", clipboard->Count());
178 result = B_OK;
183 reply.what = B_REG_RESULT;
184 reply.AddInt32("result", result);
185 message->SendReply(&reply);
186 break;
189 default:
190 BHandler::MessageReceived(message);
191 break;
196 /*! \brief Gets the clipboard with the specified name, or adds it, if not yet
197 existent.
199 \param name The name of the clipboard to be returned.
200 \return The clipboard with the respective name.
202 Clipboard*
203 ClipboardHandler::_GetClipboard(const char *name)
205 if (!name)
206 name = "system";
208 Clipboard *clipboard = NULL;
209 ClipboardMap::iterator it = fClipboards->find(name);
210 if (it != fClipboards->end()) {
211 clipboard = it->second;
212 } else {
213 clipboard = new Clipboard(name);
214 (*fClipboards)[name] = clipboard;
217 return clipboard;