vfs: check userland buffers before reading them.
[haiku.git] / src / kits / app / Handler.cpp
blob72f4b38368ed6b5218d862445fc62129e11c40bb
1 /*
2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 * Erik Jaesler, erik@cgsoftware.com
8 */
11 #include <TokenSpace.h>
13 #include <AppDefs.h>
14 #include <Handler.h>
15 #include <Looper.h>
16 #include <Message.h>
17 #include <MessageFilter.h>
18 #include <Messenger.h>
19 #include <PropertyInfo.h>
21 #include <algorithm>
22 #include <new>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <vector>
28 using std::map;
29 using std::vector;
30 using BPrivate::gDefaultTokens;
33 static const char* kArchiveNameField = "_name";
35 static const uint32 kMsgStartObserving = '_OBS';
36 static const uint32 kMsgStopObserving = '_OBP';
37 static const char* kObserveTarget = "be:observe_target";
40 static property_info sHandlerPropInfo[] = {
42 "Suites", // name
43 { B_GET_PROPERTY }, // commands
44 { B_DIRECT_SPECIFIER }, // specifiers
45 NULL, // usage
46 0, // extra data
47 { 0 }, // types
48 { // ctypes (compound_type)
49 { // ctypes[0]
50 { // pairs[0]
52 "suites", // name
53 B_STRING_TYPE // type
57 { // ctypes[1]
58 { // pairs[0]
60 "messages",
61 B_PROPERTY_INFO_TYPE
66 {} // reserved
69 "Messenger",
70 { B_GET_PROPERTY },
71 { B_DIRECT_SPECIFIER },
72 NULL, 0,
73 { B_MESSENGER_TYPE },
74 {},
78 "InternalName",
79 { B_GET_PROPERTY },
80 { B_DIRECT_SPECIFIER },
81 NULL, 0,
82 { B_STRING_TYPE },
83 {},
87 { 0 }
90 bool FilterDeleter(void* filter);
92 namespace BPrivate {
94 class ObserverList {
95 public:
96 ObserverList();
97 ~ObserverList();
99 status_t SendNotices(uint32 what, const BMessage* notice);
100 status_t Add(const BHandler* handler, uint32 what);
101 status_t Add(const BMessenger& messenger, uint32 what);
102 status_t Remove(const BHandler* handler, uint32 what);
103 status_t Remove(const BMessenger& messenger, uint32 what);
104 bool IsEmpty();
106 private:
107 typedef map<uint32, vector<const BHandler*> > HandlerObserverMap;
108 typedef map<uint32, vector<BMessenger> > MessengerObserverMap;
110 void _ValidateHandlers(uint32 what);
111 void _SendNotices(uint32 what, BMessage* notice);
113 HandlerObserverMap fHandlerMap;
114 MessengerObserverMap fMessengerMap;
117 } // namespace BPrivate
119 using namespace BPrivate;
122 // #pragma mark -
125 BHandler::BHandler(const char* name)
126 : BArchivable(),
127 fName(NULL)
129 _InitData(name);
133 BHandler::~BHandler()
135 if (LockLooper()) {
136 BLooper* looper = Looper();
137 looper->RemoveHandler(this);
138 looper->Unlock();
141 // remove all filters
142 if (fFilters) {
143 int32 count = fFilters->CountItems();
144 for (int32 i = 0; i < count; i++)
145 delete (BMessageFilter*)fFilters->ItemAtFast(i);
146 delete fFilters;
149 // remove all observers (the observer list manages itself)
150 delete fObserverList;
152 // free rest
153 free(fName);
154 gDefaultTokens.RemoveToken(fToken);
158 BHandler::BHandler(BMessage* data)
159 : BArchivable(data),
160 fName(NULL)
162 const char* name = NULL;
164 if (data)
165 data->FindString(kArchiveNameField, &name);
167 _InitData(name);
171 BArchivable*
172 BHandler::Instantiate(BMessage* data)
174 if (!validate_instantiation(data, "BHandler"))
175 return NULL;
177 return new BHandler(data);
181 status_t
182 BHandler::Archive(BMessage* data, bool deep) const
184 status_t status = BArchivable::Archive(data, deep);
185 if (status < B_OK)
186 return status;
188 if (fName == NULL)
189 return B_OK;
191 return data->AddString(kArchiveNameField, fName);
195 void
196 BHandler::MessageReceived(BMessage* message)
198 BMessage reply(B_REPLY);
200 switch (message->what) {
201 case kMsgStartObserving:
202 case kMsgStopObserving:
204 BMessenger target;
205 uint32 what;
206 if (message->FindMessenger(kObserveTarget, &target) != B_OK
207 || message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what)
208 != B_OK) {
209 break;
212 ObserverList* list = _ObserverList();
213 if (list != NULL) {
214 if (message->what == kMsgStartObserving)
215 list->Add(target, what);
216 else
217 list->Remove(target, what);
219 break;
222 case B_GET_PROPERTY:
224 int32 cur;
225 BMessage specifier;
226 int32 form;
227 const char* prop;
229 status_t err = message->GetCurrentSpecifier(&cur, &specifier,
230 &form, &prop);
231 if (err != B_OK && err != B_BAD_SCRIPT_SYNTAX)
232 break;
233 bool known = false;
234 // B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
235 if (err == B_BAD_SCRIPT_SYNTAX || cur < 0
236 || (strcmp(prop, "Messenger") == 0)) {
237 err = reply.AddMessenger("result", this);
238 known = true;
239 } else if (strcmp(prop, "Suites") == 0) {
240 err = GetSupportedSuites(&reply);
241 known = true;
242 } else if (strcmp(prop, "InternalName") == 0) {
243 err = reply.AddString("result", Name());
244 known = true;
247 if (known) {
248 reply.AddInt32("error", B_OK);
249 message->SendReply(&reply);
250 return;
252 // let's try next handler
253 break;
256 case B_GET_SUPPORTED_SUITES:
258 reply.AddInt32("error", GetSupportedSuites(&reply));
259 message->SendReply(&reply);
260 return;
264 // ToDo: there is some more work needed here
265 // (someone in the know should fill in)!
267 if (fNextHandler) {
268 // we need to apply the next handler's filters here, too
269 BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
270 if (target != NULL && target != this) {
271 // TODO: we also need to make sure that "target" is not before
272 // us in the handler chain - at least in case it wasn't before
273 // the handler actually targeted with this message - this could
274 // get ugly, though.
275 target->MessageReceived(message);
277 } else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
278 && (message->WasDropped() || message->HasSpecifiers())) {
279 printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
280 message->PrintToStream();
281 message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
286 BLooper*
287 BHandler::Looper() const
289 return fLooper;
293 void
294 BHandler::SetName(const char* name)
296 if (fName != NULL) {
297 free(fName);
298 fName = NULL;
301 if (name != NULL)
302 fName = strdup(name);
306 const char*
307 BHandler::Name() const
309 return fName;
313 void
314 BHandler::SetNextHandler(BHandler* handler)
316 if (fLooper == NULL) {
317 debugger("handler must belong to looper before setting NextHandler");
318 return;
321 if (!fLooper->IsLocked()) {
322 debugger("The handler's looper must be locked before setting NextHandler");
323 return;
326 if (handler != NULL && fLooper != handler->Looper()) {
327 debugger("The handler and its NextHandler must have the same looper");
328 return;
331 fNextHandler = handler;
335 BHandler*
336 BHandler::NextHandler() const
338 return fNextHandler;
342 void
343 BHandler::AddFilter(BMessageFilter* filter)
345 BLooper* looper = fLooper;
346 if (looper != NULL && !looper->IsLocked()) {
347 debugger("Owning Looper must be locked before calling SetFilterList");
348 return;
351 if (looper != NULL)
352 filter->SetLooper(looper);
354 if (fFilters == NULL)
355 fFilters = new BList;
357 fFilters->AddItem(filter);
361 bool
362 BHandler::RemoveFilter(BMessageFilter* filter)
364 BLooper* looper = fLooper;
365 if (looper != NULL && !looper->IsLocked()) {
366 debugger("Owning Looper must be locked before calling SetFilterList");
367 return false;
370 if (fFilters != NULL && fFilters->RemoveItem((void*)filter)) {
371 filter->SetLooper(NULL);
372 return true;
375 return false;
379 void
380 BHandler::SetFilterList(BList* filters)
382 BLooper* looper = fLooper;
383 if (looper != NULL && !looper->IsLocked()) {
384 debugger("Owning Looper must be locked before calling SetFilterList");
385 return;
389 @note I would like to use BObjectList internally, but this function is
390 spec'd such that fFilters would get deleted and then assigned
391 'filters', which would obviously mess this up. Wondering if
392 anyone ever assigns a list of filters and then checks against
393 FilterList() to see if they are the same.
396 // TODO: Explore issues with using BObjectList
397 if (fFilters != NULL) {
398 fFilters->DoForEach(FilterDeleter);
399 delete fFilters;
402 fFilters = filters;
403 if (fFilters) {
404 for (int32 i = 0; i < fFilters->CountItems(); ++i) {
405 BMessageFilter* filter =
406 static_cast<BMessageFilter*>(fFilters->ItemAt(i));
407 if (filter != NULL)
408 filter->SetLooper(looper);
414 BList*
415 BHandler::FilterList()
417 return fFilters;
421 bool
422 BHandler::LockLooper()
424 BLooper* looper = fLooper;
425 // Locking the looper also makes sure that the looper is valid
426 if (looper != NULL && looper->Lock()) {
427 // Have we locked the right looper? That's as far as the
428 // "pseudo-atomic" operation mentioned in the BeBook.
429 if (fLooper == looper)
430 return true;
432 // we locked the wrong looper, bail out
433 looper->Unlock();
436 return false;
440 status_t
441 BHandler::LockLooperWithTimeout(bigtime_t timeout)
443 BLooper* looper = fLooper;
444 if (looper == NULL)
445 return B_BAD_VALUE;
447 status_t status = looper->LockWithTimeout(timeout);
448 if (status != B_OK)
449 return status;
451 if (fLooper != looper) {
452 // we locked the wrong looper, bail out
453 looper->Unlock();
454 return B_MISMATCHED_VALUES;
457 return B_OK;
461 void
462 BHandler::UnlockLooper()
464 fLooper->Unlock();
468 BHandler*
469 BHandler::ResolveSpecifier(BMessage* message, int32 index,
470 BMessage* specifier, int32 what, const char* property)
472 // Straight from the BeBook
473 BPropertyInfo propertyInfo(sHandlerPropInfo);
474 if (propertyInfo.FindMatch(message, index, specifier, what, property) >= 0)
475 return this;
477 BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
478 reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
479 reply.AddString("message", "Didn't understand the specifier(s)");
480 message->SendReply(&reply);
482 return NULL;
486 status_t
487 BHandler::GetSupportedSuites(BMessage* data)
490 @note This is the output from the original implementation (calling
491 PrintToStream() on both data and the contained BPropertyInfo):
493 BMessage: what = (0x0, or 0)
494 entry suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
495 entry messages, type='SCTD', c=1, size= 0,
496 property commands types specifiers
497 --------------------------------------------------------------------------------
498 Suites PGET 1
499 (RTSC,suites)
500 (DTCS,messages)
502 Messenger PGET GNSM 1
503 InternalName PGET RTSC 1
505 With a good deal of trial and error, I determined that the
506 parenthetical clauses are entries in the 'ctypes' field of
507 property_info. 'ctypes' is an array of 'compound_type', which
508 contains an array of 'field_pair's. I haven't the foggiest what
509 either 'compound_type' or 'field_pair' is for, being as the
510 scripting docs are so bloody horrible. The corresponding
511 property_info array is declared in the globals section.
514 if (data == NULL)
515 return B_BAD_VALUE;
517 status_t result = data->AddString("suites", "suite/vnd.Be-handler");
518 if (result == B_OK) {
519 BPropertyInfo propertyInfo(sHandlerPropInfo);
520 result = data->AddFlat("messages", &propertyInfo);
523 return result;
527 status_t
528 BHandler::StartWatching(BMessenger target, uint32 what)
530 BMessage message(kMsgStartObserving);
531 message.AddMessenger(kObserveTarget, this);
532 message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
534 return target.SendMessage(&message);
538 status_t
539 BHandler::StartWatchingAll(BMessenger target)
541 return StartWatching(target, B_OBSERVER_OBSERVE_ALL);
545 status_t
546 BHandler::StopWatching(BMessenger target, uint32 what)
548 BMessage message(kMsgStopObserving);
549 message.AddMessenger(kObserveTarget, this);
550 message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
552 return target.SendMessage(&message);
556 status_t
557 BHandler::StopWatchingAll(BMessenger target)
559 return StopWatching(target, B_OBSERVER_OBSERVE_ALL);
563 status_t
564 BHandler::StartWatching(BHandler* handler, uint32 what)
566 ObserverList* list = _ObserverList();
567 if (list == NULL)
568 return B_NO_MEMORY;
570 return list->Add(handler, what);
574 status_t
575 BHandler::StartWatchingAll(BHandler* handler)
577 return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
581 status_t
582 BHandler::StopWatching(BHandler* handler, uint32 what)
584 ObserverList* list = _ObserverList();
585 if (list == NULL)
586 return B_NO_MEMORY;
588 return list->Remove(handler, what);
592 status_t
593 BHandler::StopWatchingAll(BHandler* handler)
595 return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
599 status_t
600 BHandler::Perform(perform_code d, void* arg)
602 return BArchivable::Perform(d, arg);
606 void
607 BHandler::SendNotices(uint32 what, const BMessage* notice)
609 if (fObserverList != NULL)
610 fObserverList->SendNotices(what, notice);
614 bool
615 BHandler::IsWatched() const
617 return fObserverList && !fObserverList->IsEmpty();
621 void
622 BHandler::_InitData(const char* name)
624 SetName(name);
626 fLooper = NULL;
627 fNextHandler = NULL;
628 fFilters = NULL;
629 fObserverList = NULL;
631 fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
635 ObserverList*
636 BHandler::_ObserverList()
638 if (fObserverList == NULL)
639 fObserverList = new (std::nothrow) BPrivate::ObserverList();
641 return fObserverList;
645 BHandler::BHandler(const BHandler &)
647 // No copy construction allowed.
651 BHandler &
652 BHandler::operator=(const BHandler &)
654 // No assignments allowed.
655 return *this;
659 void
660 BHandler::SetLooper(BLooper* looper)
662 fLooper = looper;
663 gDefaultTokens.SetHandlerTarget(fToken,
664 looper ? looper->fDirectTarget : NULL);
666 if (fFilters != NULL) {
667 for (int32 i = 0; i < fFilters->CountItems(); i++) {
668 static_cast<BMessageFilter*>(
669 fFilters->ItemAtFast(i))->SetLooper(looper);
675 #if __GNUC__ < 3
676 // binary compatibility with R4.5
678 extern "C" void
679 _ReservedHandler1__8BHandler(BHandler* handler, uint32 what,
680 const BMessage* notice)
682 handler->BHandler::SendNotices(what, notice);
685 #endif
687 void BHandler::_ReservedHandler2() {}
688 void BHandler::_ReservedHandler3() {}
689 void BHandler::_ReservedHandler4() {}
692 // #pragma mark -
695 ObserverList::ObserverList()
700 ObserverList::~ObserverList()
705 void
706 ObserverList::_ValidateHandlers(uint32 what)
708 vector<const BHandler*>& handlers = fHandlerMap[what];
709 vector<const BHandler*>::iterator iterator = handlers.begin();
711 while (iterator != handlers.end()) {
712 BMessenger target(*iterator);
713 if (!target.IsValid()) {
714 iterator++;
715 continue;
718 Add(target, what);
719 iterator = handlers.erase(iterator);
724 void
725 ObserverList::_SendNotices(uint32 what, BMessage* notice)
727 // first iterate over the list of handlers and try to make valid
728 // messengers out of them
729 _ValidateHandlers(what);
731 // now send it to all messengers we know
732 vector<BMessenger>& messengers = fMessengerMap[what];
733 vector<BMessenger>::iterator iterator = messengers.begin();
735 while (iterator != messengers.end()) {
736 if (!(*iterator).IsValid()) {
737 iterator = messengers.erase(iterator);
738 continue;
741 (*iterator).SendMessage(notice);
742 iterator++;
747 status_t
748 ObserverList::SendNotices(uint32 what, const BMessage* notice)
750 BMessage* copy = NULL;
751 if (notice != NULL) {
752 copy = new BMessage(*notice);
753 copy->what = B_OBSERVER_NOTICE_CHANGE;
754 copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, notice->what);
755 } else
756 copy = new BMessage(B_OBSERVER_NOTICE_CHANGE);
758 copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
760 _SendNotices(what, copy);
761 _SendNotices(B_OBSERVER_OBSERVE_ALL, copy);
763 delete copy;
765 return B_OK;
769 status_t
770 ObserverList::Add(const BHandler* handler, uint32 what)
772 if (handler == NULL)
773 return B_BAD_HANDLER;
775 // if this handler already represents a valid target, add its messenger
776 BMessenger target(handler);
777 if (target.IsValid())
778 return Add(target, what);
780 vector<const BHandler*> &handlers = fHandlerMap[what];
782 vector<const BHandler*>::iterator iter;
783 iter = find(handlers.begin(), handlers.end(), handler);
784 if (iter != handlers.end()) {
785 // TODO: do we want to have a reference count for this?
786 return B_OK;
789 handlers.push_back(handler);
790 return B_OK;
794 status_t
795 ObserverList::Add(const BMessenger &messenger, uint32 what)
797 vector<BMessenger> &messengers = fMessengerMap[what];
799 vector<BMessenger>::iterator iter;
800 iter = find(messengers.begin(), messengers.end(), messenger);
801 if (iter != messengers.end()) {
802 // TODO: do we want to have a reference count for this?
803 return B_OK;
806 messengers.push_back(messenger);
807 return B_OK;
811 status_t
812 ObserverList::Remove(const BHandler* handler, uint32 what)
814 if (handler == NULL)
815 return B_BAD_HANDLER;
817 // look into the list of messengers
818 BMessenger target(handler);
819 if (target.IsValid() && Remove(target, what) == B_OK)
820 return B_OK;
822 vector<const BHandler*> &handlers = fHandlerMap[what];
824 vector<const BHandler*>::iterator iterator = find(handlers.begin(),
825 handlers.end(), handler);
826 if (iterator != handlers.end()) {
827 handlers.erase(iterator);
828 if (handlers.empty())
829 fHandlerMap.erase(what);
831 return B_OK;
834 return B_BAD_HANDLER;
838 status_t
839 ObserverList::Remove(const BMessenger &messenger, uint32 what)
841 vector<BMessenger> &messengers = fMessengerMap[what];
843 vector<BMessenger>::iterator iterator = find(messengers.begin(),
844 messengers.end(), messenger);
845 if (iterator != messengers.end()) {
846 messengers.erase(iterator);
847 if (messengers.empty())
848 fMessengerMap.erase(what);
850 return B_OK;
853 return B_BAD_HANDLER;
857 bool
858 ObserverList::IsEmpty()
860 return fHandlerMap.empty() && fMessengerMap.empty();
864 // #pragma mark -
867 bool
868 FilterDeleter(void* _filter)
870 delete static_cast<BMessageFilter*>(_filter);
871 return false;