vfs: check userland buffers before reading them.
[haiku.git] / src / servers / registrar / RecentApps.cpp
blob8b949d6e2efbf579c67397e2145026efa929cd7c
1 /*
2 * Copyright 2001-2009, Haiku Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Tyler Dauwalder
7 * Ingo Weinhold, bonefish@users.sf.net
8 * Axel Dörfler, axeld@pinc-software.de
9 */
12 //! Recently launched apps list
15 #include "RecentApps.h"
17 #include <tracker_private.h>
19 #include <AppFileInfo.h>
20 #include <Entry.h>
21 #include <File.h>
22 #include <Message.h>
23 #include <Mime.h>
24 #include <Roster.h>
25 #include <storage_support.h>
27 #include <strings.h>
29 #include "Debug.h"
32 /*! \class RecentApps
33 \brief Manages the roster's list of recently launched applications
38 /*! \var std::list<std::string> RecentApps::fAppList
39 \brief The list of app sigs, most recent first
41 The signatures are expected to be stored all lowercase, as MIME
42 signatures are case-independent.
46 /*! \brief Creates a new list.
48 The list is initially empty.
50 RecentApps::RecentApps()
55 /*! \brief Frees all resources associated with the object.
57 Currently does nothing.
59 RecentApps::~RecentApps()
64 /*! \brief Places the app with the given signature at the front of
65 the recent apps list.
67 If the app already exists elsewhere in the list, that item is
68 removed so only one instance exists in the list at any time.
70 \param appSig The application's signature
71 \param appFlags The application's flags. If \a appFlags contains
72 either \c B_ARGV_ONLY or \c B_BACKGROUND_APP, the
73 application is \b not added to the list (but \c B_OK
74 is still returned).
75 \return
76 - \c B_OK: success (even if the app was not added due to appFlags)
77 - error code: failure
79 status_t
80 RecentApps::Add(const char *appSig, int32 appFlags)
82 if (appSig == NULL)
83 return B_BAD_VALUE;
85 // don't add background apps, as well as Tracker and Deskbar to the list
86 // of recent apps
87 if (!strcasecmp(appSig, kTrackerSignature)
88 || !strcasecmp(appSig, kDeskbarSignature)
89 || (appFlags & (B_ARGV_ONLY | B_BACKGROUND_APP)) != 0)
90 return B_OK;
92 // Remove any previous instance
93 std::list<std::string>::iterator i;
94 for (i = fAppList.begin(); i != fAppList.end(); i++) {
95 if (!strcasecmp((*i).c_str(), appSig)) {
96 fAppList.erase(i);
97 break;
101 try {
102 // Add to the front
103 fAppList.push_front(appSig);
104 } catch (...) {
105 return B_NO_MEMORY;
108 return B_OK;
112 /*! \brief Adds the signature of the application referred to by \a ref at
113 the front of the recent apps list.
115 The entry is checked for a BEOS:APP_SIG attribute. If that fails, the
116 app's resources are checked. If no signature can be found, the call
117 fails.
119 status_t
120 RecentApps::Add(const entry_ref *ref, int32 appFlags)
122 if (ref == NULL)
123 return B_BAD_VALUE;
125 BFile file;
126 BAppFileInfo info;
127 char signature[B_MIME_TYPE_LENGTH];
129 status_t err = file.SetTo(ref, B_READ_ONLY);
130 if (!err)
131 err = info.SetTo(&file);
132 if (!err)
133 err = info.GetSignature(signature);
134 if (!err)
135 err = Add(signature, appFlags);
136 return err;
140 /*! \brief Returns the first \a maxCount recent apps in the \c BMessage
141 pointed to by \a list.
143 The message is cleared first, and \c entry_refs for the the apps are
144 stored in the \c "refs" field of the message (\c B_REF_TYPE).
146 If there are fewer than \a maxCount items in the list, the entire
147 list is returned.
149 Since BRoster::GetRecentApps() returns \c void, the message pointed
150 to by \a list is simply cleared if maxCount is invalid (i.e. <= 0).
152 status_t
153 RecentApps::Get(int32 maxCount, BMessage *list)
155 if (list == NULL)
156 return B_BAD_VALUE;
158 // Clear
159 list->MakeEmpty();
161 // Fill
162 std::list<std::string>::iterator item;
163 status_t status = B_OK;
164 int counter = 0;
165 for (item = fAppList.begin();
166 status == B_OK && counter < maxCount && item != fAppList.end();
167 counter++, item++) {
168 entry_ref ref;
169 if (GetRefForApp(item->c_str(), &ref) == B_OK)
170 status = list->AddRef("refs", &ref);
171 else {
172 D(PRINT("WARNING: RecentApps::Get(): No ref found for app '%s'\n",
173 item->c_str()));
177 return status;
181 /*! \brief Clears the list of recently launched apps
183 status_t
184 RecentApps::Clear()
186 fAppList.clear();
187 return B_OK;
191 /*! \brief Dumps the the current list of apps to stdout.
193 status_t
194 RecentApps::Print()
196 std::list<std::string>::iterator item;
197 int counter = 1;
198 for (item = fAppList.begin(); item != fAppList.end(); item++) {
199 printf("%d: '%s'\n", counter++, item->c_str());
201 return B_OK;
205 /*! \brief Outputs a textual representation of the current recent
206 apps list to the given file stream.
209 status_t
210 RecentApps::Save(FILE* file)
212 status_t error = file ? B_OK : B_BAD_VALUE;
213 if (!error) {
214 fprintf(file, "# Recent applications\n");
215 std::list<std::string>::iterator item;
216 for (item = fAppList.begin(); item != fAppList.end(); item++) {
217 fprintf(file, "RecentApp %s\n", item->c_str());
219 fprintf(file, "\n");
221 return error;
225 /*! \brief Fetches an \c entry_ref for the application with the
226 given signature.
228 First the MIME database is checked for a matching application type
229 with a valid app hint attribute. If that fails, a query is established
230 to track down such an application, if there is one available.
232 status_t
233 RecentApps::GetRefForApp(const char *appSig, entry_ref *result)
235 if (appSig == NULL || result == NULL)
236 return B_BAD_VALUE;
238 // We'll use BMimeType to check for the app hint, since I'm lazy
239 // and Ingo's on vacation :-P :-)
240 BMimeType mime(appSig);
241 status_t err = mime.InitCheck();
242 if (!err)
243 err = mime.GetAppHint(result);
244 return err;