vfs: check userland buffers before reading them.
[haiku.git] / src / kits / app / Clipboard.cpp
bloba17ea09b11e3cd5c312de32bef286dacb3a445d1
1 /*
2 * Copyright 2001-2009, Haiku Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Gabe Yoder (gyoder@stny.rr.com)
7 */
10 #include <Clipboard.h>
12 #include <Application.h>
13 #include <RegistrarDefs.h>
14 #include <RosterPrivate.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
20 #ifdef RUN_WITHOUT_REGISTRAR
21 static BClipboard sClipboard(NULL);
22 BClipboard *be_clipboard = &sClipboard;
23 #else
24 BClipboard *be_clipboard = NULL;
25 #endif
28 using namespace BPrivate;
31 BClipboard::BClipboard(const char *name, bool transient)
33 fLock("clipboard")
35 if (name != NULL)
36 fName = strdup(name);
37 else
38 fName = strdup("system");
40 fData = new BMessage();
41 fCount = 0;
43 BMessage message(B_REG_GET_CLIPBOARD_MESSENGER), reply;
44 if (BRoster::Private().SendTo(&message, &reply, false) == B_OK
45 && reply.what == B_REG_SUCCESS
46 && reply.FindMessenger("messenger", &fClipHandler) == B_OK) {
47 BMessage handlerMessage(B_REG_ADD_CLIPBOARD), handlerReply;
48 int32 result;
49 if (handlerMessage.AddString("name", fName) == B_OK
50 && fClipHandler.SendMessage(&handlerMessage, &handlerReply) == B_OK)
51 handlerReply.FindInt32("result", &result);
56 BClipboard::~BClipboard()
58 free(fName);
59 delete fData;
63 const char *
64 BClipboard::Name() const
66 return (const char *)fName;
70 /*! \brief Returns the (locally cached) number of commits to the clipboard.
72 The returned value is the number of successful Commit() invocations for
73 the clipboard represented by this object, either invoked on this object
74 or another (even from another application). This method returns a locally
75 cached value, which might already be obsolete. For an up-to-date value
76 SystemCount() can be invoked.
78 \return The number of commits to the clipboard.
80 uint32
81 BClipboard::LocalCount() const
83 return fCount;
87 /*! \brief Returns the number of commits to the clipboard.
89 The returned value is the number of successful Commit() invocations for
90 the clipboard represented by this object, either invoked on this object
91 or another (even from another application). This method retrieves the
92 value directly from the system service managing the clipboards, so it is
93 more expensive, but more up-to-date than LocalCount(), which returns a
94 locally cached value.
96 \return The number of commits to the clipboard.
98 uint32
99 BClipboard::SystemCount() const
101 int32 value;
102 BMessage message(B_REG_GET_CLIPBOARD_COUNT), reply;
103 if (message.AddString("name", fName) == B_OK
104 && fClipHandler.SendMessage(&message, &reply) == B_OK
105 && reply.FindInt32("count", &value) == B_OK)
106 return (uint32)value;
108 return 0;
112 status_t
113 BClipboard::StartWatching(BMessenger target)
115 if (!target.IsValid())
116 return B_BAD_VALUE;
118 BMessage message(B_REG_CLIPBOARD_START_WATCHING), reply;
119 if (message.AddString("name", fName) == B_OK
120 && message.AddMessenger("target", target) == B_OK
121 && fClipHandler.SendMessage(&message, &reply) == B_OK) {
122 int32 result;
123 reply.FindInt32("result", &result);
124 return result;
126 return B_ERROR;
130 status_t
131 BClipboard::StopWatching(BMessenger target)
133 if (!target.IsValid())
134 return B_BAD_VALUE;
136 BMessage message(B_REG_CLIPBOARD_STOP_WATCHING), reply;
137 if (message.AddString("name", fName) == B_OK
138 && message.AddMessenger("target", target) == B_OK
139 && fClipHandler.SendMessage(&message, &reply) == B_OK) {
140 int32 result;
141 if (reply.FindInt32("result", &result) == B_OK)
142 return result;
144 return B_ERROR;
148 bool
149 BClipboard::Lock()
151 // Will this work correctly if clipboard is deleted while still waiting on
152 // fLock.Lock() ?
153 bool locked = fLock.Lock();
155 #ifndef RUN_WITHOUT_REGISTRAR
156 if (locked && _DownloadFromSystem() != B_OK) {
157 locked = false;
158 fLock.Unlock();
160 #endif
162 return locked;
166 void
167 BClipboard::Unlock()
169 fLock.Unlock();
173 bool
174 BClipboard::IsLocked() const
176 return fLock.IsLocked();
180 status_t
181 BClipboard::Clear()
183 if (!_AssertLocked())
184 return B_NOT_ALLOWED;
186 return fData->MakeEmpty();
190 status_t
191 BClipboard::Commit()
193 return Commit(false);
197 status_t
198 BClipboard::Commit(bool failIfChanged)
200 if (!_AssertLocked())
201 return B_NOT_ALLOWED;
203 status_t status = B_ERROR;
204 BMessage message(B_REG_UPLOAD_CLIPBOARD), reply;
205 if (message.AddString("name", fName) == B_OK
206 && message.AddMessage("data", fData) == B_OK
207 && message.AddMessenger("data source", be_app_messenger) == B_OK
208 && message.AddInt32("count", fCount) == B_OK
209 && message.AddBool("fail if changed", failIfChanged) == B_OK)
210 status = fClipHandler.SendMessage(&message, &reply);
212 if (status == B_OK) {
213 int32 count;
214 if (reply.FindInt32("count", &count) == B_OK)
215 fCount = count;
218 return status;
222 status_t
223 BClipboard::Revert()
225 if (!_AssertLocked())
226 return B_NOT_ALLOWED;
228 status_t status = fData->MakeEmpty();
229 if (status == B_OK)
230 status = _DownloadFromSystem();
232 return status;
236 BMessenger
237 BClipboard::DataSource() const
239 return fDataSource;
243 BMessage *
244 BClipboard::Data() const
246 if (!_AssertLocked())
247 return NULL;
249 return fData;
253 // #pragma mark - Private methods
256 BClipboard::BClipboard(const BClipboard &)
258 // This is private, and I don't use it, so I'm not going to implement it
262 BClipboard & BClipboard::operator=(const BClipboard &)
264 // This is private, and I don't use it, so I'm not going to implement it
265 return *this;
269 void BClipboard::_ReservedClipboard1() {}
270 void BClipboard::_ReservedClipboard2() {}
271 void BClipboard::_ReservedClipboard3() {}
274 bool
275 BClipboard::_AssertLocked() const
277 // This function is for jumping to the debugger if not locked
278 if (!fLock.IsLocked()) {
279 debugger("The clipboard must be locked before proceeding.");
280 return false;
282 return true;
286 status_t
287 BClipboard::_DownloadFromSystem(bool force)
289 // Apparently, the force paramater was used in some sort of
290 // optimization in R5. Currently, we ignore it.
291 BMessage message(B_REG_DOWNLOAD_CLIPBOARD), reply;
292 if (message.AddString("name", fName) == B_OK
293 && fClipHandler.SendMessage(&message, &reply) == B_OK
294 && reply.FindMessage("data", fData) == B_OK
295 && reply.FindMessenger("data source", &fDataSource) == B_OK
296 && reply.FindInt32("count", (int32 *)&fCount) == B_OK)
297 return B_OK;
299 return B_ERROR;