xref: /haiku/src/kits/tracker/infowindow/FilePermissionsView.cpp (revision 4b918abdb02a26a770d898594eaaccc6f1726e9b)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 
36 #include "FilePermissionsView.h"
37 
38 #include <algorithm>
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #include <Beep.h>
43 #include <Catalog.h>
44 #include <LayoutBuilder.h>
45 #include <Locale.h>
46 
47 
48 #undef B_TRANSLATION_CONTEXT
49 #define B_TRANSLATION_CONTEXT "FilePermissionsView"
50 
51 
52 const uint32 kPermissionsChanged = 'prch';
53 const uint32 kNewOwnerEntered = 'nwow';
54 const uint32 kNewGroupEntered = 'nwgr';
55 
56 
57 class RotatedStringView: public BStringView
58 {
59 public:
60 	RotatedStringView(const char* name, const char* label)
61 		: BStringView(name, label)
62 	{
63 		BFont currentFont;
64 		GetFont(&currentFont);
65 
66 		currentFont.SetRotation(57);
67 		SetFont(&currentFont);
68 
69 		// Get the dimension of the bounding box of the string, taking care
70 		// of the orientation
71 		const char* stringArray[1];
72 		stringArray[0] = label;
73 		BRect rectArray[1];
74 		escapement_delta delta = { 0.0, 0.0 };
75 		currentFont.GetBoundingBoxesForStrings(stringArray, 1, B_SCREEN_METRIC,
76 			&delta,	rectArray);
77 
78 		// Adjust the size to avoid partial drawing of first and last chars
79 		// due to the orientation
80 		fExplicitSize = BSize(rectArray[0].Width(), rectArray[0].Height()
81 			+ currentFont.Size() / 2);
82 
83 		SetExplicitSize(fExplicitSize);
84 	}
85 
86 	void Draw(BRect invalidate)
87 	{
88 		BFont currentFont;
89 		GetFont(&currentFont);
90 
91 		// Small adjustment to draw in the calculated area
92 		TranslateBy(currentFont.Size() / 1.9 + 1, 0);
93 
94 		BStringView::Draw(invalidate);
95 	}
96 
97 	BSize ExplicitSize()
98 	{
99 		return fExplicitSize;
100 	}
101 
102 private:
103 	BSize fExplicitSize;
104 };
105 
106 
107 //	#pragma mark - FilePermissionsView
108 
109 
110 FilePermissionsView::FilePermissionsView(BRect rect, Model* model)
111 	:
112 	BView(rect, B_TRANSLATE("Permissions"), B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW),
113 	fModel(model)
114 {
115 	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
116 
117 	RotatedStringView* ownerRightLabel = new RotatedStringView("",
118 		B_TRANSLATE("Owner"));
119 	RotatedStringView* groupRightLabel = new RotatedStringView("",
120 		B_TRANSLATE("Group"));
121 	RotatedStringView* otherRightLabel = new RotatedStringView("",
122 		B_TRANSLATE("Other"));
123 
124 	// Get the largest inclined area of the three
125 	BSize ownerRightLabelSize, groupRightLabelSize, maxSize;
126 
127 	ownerRightLabelSize = ownerRightLabel->ExplicitSize();
128 	groupRightLabelSize = groupRightLabel->ExplicitSize();
129 
130 	maxSize.width = std::max(ownerRightLabelSize.width,
131 		groupRightLabelSize.width);
132 	maxSize.width = std::max(maxSize.width,
133 		otherRightLabel->ExplicitSize().width);
134 
135 	maxSize.height = std::max(ownerRightLabel->ExplicitSize().height,
136 		groupRightLabel->ExplicitSize().height);
137 	maxSize.height = std::max(maxSize.height,
138 		otherRightLabel->ExplicitSize().height);
139 
140 
141 	// Set all the component with this size
142 	ownerRightLabel->SetExplicitSize(maxSize);
143 	groupRightLabel->SetExplicitSize(maxSize);
144 	otherRightLabel->SetExplicitSize(maxSize);
145 
146 	BStringView* readLabel = new BStringView("", B_TRANSLATE("Read"));
147 	readLabel->SetAlignment(B_ALIGN_RIGHT);
148 
149 	BStringView* writeLabel = new BStringView("", B_TRANSLATE("Write"));
150 	writeLabel->SetAlignment(B_ALIGN_RIGHT);
151 
152 	BStringView* executeLabel = new BStringView("", B_TRANSLATE("Execute"));
153 	executeLabel->SetAlignment(B_ALIGN_RIGHT);
154 
155 	// Creating checkbox
156 	fReadUserCheckBox = new BCheckBox("", "",
157 		new BMessage(kPermissionsChanged));
158 	fReadGroupCheckBox = new BCheckBox("", "",
159 		new BMessage(kPermissionsChanged));
160 	fReadOtherCheckBox = new BCheckBox("", "",
161 		new BMessage(kPermissionsChanged));
162 
163 	fWriteUserCheckBox = new BCheckBox("", "",
164 		new BMessage(kPermissionsChanged));
165 	fWriteGroupCheckBox = new BCheckBox("", "",
166 		new BMessage(kPermissionsChanged));
167 	fWriteOtherCheckBox = new BCheckBox("", "",
168 		new BMessage(kPermissionsChanged));
169 
170 	fExecuteUserCheckBox = new BCheckBox("", "",
171 		new BMessage(kPermissionsChanged));
172 	fExecuteGroupCheckBox = new BCheckBox("", "",
173 		new BMessage(kPermissionsChanged));
174 	fExecuteOtherCheckBox = new BCheckBox("", "",
175 		new BMessage(kPermissionsChanged));
176 
177 	fOwnerTextControl = new BTextControl("", B_TRANSLATE("Owner"), "",
178 		new BMessage(kNewOwnerEntered));
179 	fGroupTextControl = new BTextControl("", B_TRANSLATE("Group"), "",
180 		new BMessage(kNewGroupEntered));
181 
182 	BGroupLayout* groupLayout = new BGroupLayout(B_HORIZONTAL);
183 
184 	SetLayout(groupLayout);
185 
186 	BLayoutBuilder::Group<>(groupLayout)
187 		.SetInsets(B_USE_DEFAULT_SPACING)
188 		.AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
189 			.Add(ownerRightLabel, 1, 0)
190 			.Add(groupRightLabel, 2, 0)
191 			.Add(otherRightLabel, 3, 0)
192 			.Add(readLabel, 0, 1)
193 			.Add(writeLabel, 0, 2)
194 			.Add(executeLabel, 0, 3)
195 			.Add(fReadUserCheckBox, 1, 1)
196 			.Add(fReadGroupCheckBox, 1, 2)
197 			.Add(fReadOtherCheckBox, 1, 3)
198 			.Add(fWriteUserCheckBox, 2, 1)
199 			.Add(fWriteGroupCheckBox, 2, 2)
200 			.Add(fWriteOtherCheckBox, 2, 3)
201 			.Add(fExecuteUserCheckBox, 3, 1)
202 			.Add(fExecuteGroupCheckBox, 3, 2)
203 			.Add(fExecuteOtherCheckBox, 3, 3)
204 			.AddGlue(0, 4)
205 		.End()
206 		.AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
207 			.AddGlue(0, 0)
208 			.AddTextControl(fOwnerTextControl, 0, 1)
209 			.AddTextControl(fGroupTextControl, 0, 2)
210 			.AddGlue(0, 3)
211 		.End()
212 		.AddGlue();
213 
214 	ModelChanged(model);
215 }
216 
217 
218 void
219 FilePermissionsView::ModelChanged(Model* model)
220 {
221 	fModel = model;
222 
223 	bool hideCheckBoxes = false;
224 	uid_t nodeOwner = 0;
225 	gid_t nodeGroup = 0;
226 	mode_t perms = 0;
227 
228 	if (fModel != NULL) {
229 		BNode node(fModel->EntryRef());
230 
231 		if (node.InitCheck() == B_OK) {
232 			if (fReadUserCheckBox->IsHidden()) {
233 				fReadUserCheckBox->Show();
234 				fReadGroupCheckBox->Show();
235 				fReadOtherCheckBox->Show();
236 				fWriteUserCheckBox->Show();
237 				fWriteGroupCheckBox->Show();
238 				fWriteOtherCheckBox->Show();
239 				fExecuteUserCheckBox->Show();
240 				fExecuteGroupCheckBox->Show();
241 				fExecuteOtherCheckBox->Show();
242 			}
243 
244 			if (node.GetPermissions(&perms) == B_OK) {
245 				fReadUserCheckBox->SetValue((int32)(perms & S_IRUSR));
246 				fReadGroupCheckBox->SetValue((int32)(perms & S_IRGRP));
247 				fReadOtherCheckBox->SetValue((int32)(perms & S_IROTH));
248 				fWriteUserCheckBox->SetValue((int32)(perms & S_IWUSR));
249 				fWriteGroupCheckBox->SetValue((int32)(perms & S_IWGRP));
250 				fWriteOtherCheckBox->SetValue((int32)(perms & S_IWOTH));
251 				fExecuteUserCheckBox->SetValue((int32)(perms & S_IXUSR));
252 				fExecuteGroupCheckBox->SetValue((int32)(perms & S_IXGRP));
253 				fExecuteOtherCheckBox->SetValue((int32)(perms & S_IXOTH));
254 			} else
255 				hideCheckBoxes = true;
256 
257 			if (node.GetOwner(&nodeOwner) == B_OK) {
258 				BString user;
259 				if (nodeOwner == 0)
260 					if (getenv("USER") != NULL)
261 						user << getenv("USER");
262 					else
263 						user << "root";
264 				else
265 					user << nodeOwner;
266 				fOwnerTextControl->SetText(user.String());
267 			} else
268 				fOwnerTextControl->SetText(B_TRANSLATE("Unknown"));
269 
270 			if (node.GetGroup(&nodeGroup) == B_OK) {
271 				BString group;
272 				if (nodeGroup == 0)
273 					if (getenv("GROUP") != NULL)
274 						group << getenv("GROUP");
275 					else
276 						group << "0";
277 				else
278 					group << nodeGroup;
279 				fGroupTextControl->SetText(group.String());
280 			} else
281 				fGroupTextControl->SetText(B_TRANSLATE("Unknown"));
282 
283 			// Unless we're root, only allow the owner to transfer the
284 			// ownership, i.e. disable text controls if uid:s doesn't match:
285 			thread_id thisThread = find_thread(NULL);
286 			thread_info threadInfo;
287 			get_thread_info(thisThread, &threadInfo);
288 			team_info teamInfo;
289 			get_team_info(threadInfo.team, &teamInfo);
290 			if (teamInfo.uid != 0 && nodeOwner != teamInfo.uid) {
291 				fOwnerTextControl->SetEnabled(false);
292 				fGroupTextControl->SetEnabled(false);
293 			} else {
294 				fOwnerTextControl->SetEnabled(true);
295 				fGroupTextControl->SetEnabled(true);
296 			}
297 		} else
298 			hideCheckBoxes = true;
299 	} else
300 		hideCheckBoxes = true;
301 
302 	if (hideCheckBoxes) {
303 		fReadUserCheckBox->Hide();
304 		fReadGroupCheckBox->Hide();
305 		fReadOtherCheckBox->Hide();
306 		fWriteUserCheckBox->Hide();
307 		fWriteGroupCheckBox->Hide();
308 		fWriteOtherCheckBox->Hide();
309 		fExecuteUserCheckBox->Hide();
310 		fExecuteGroupCheckBox->Hide();
311 		fExecuteOtherCheckBox->Hide();
312 	}
313 }
314 
315 
316 void
317 FilePermissionsView::MessageReceived(BMessage* message)
318 {
319 	switch(message->what) {
320 		case kPermissionsChanged:
321 			if (fModel != NULL) {
322 				mode_t newPermissions = 0;
323 				newPermissions
324 					= (mode_t)((fReadUserCheckBox->Value() ? S_IRUSR : 0)
325 					| (fReadGroupCheckBox->Value() ? S_IRGRP : 0)
326 					| (fReadOtherCheckBox->Value() ? S_IROTH : 0)
327 
328 					| (fWriteUserCheckBox->Value() ? S_IWUSR : 0)
329 					| (fWriteGroupCheckBox->Value() ? S_IWGRP : 0)
330 					| (fWriteOtherCheckBox->Value() ? S_IWOTH : 0)
331 
332 					| (fExecuteUserCheckBox->Value() ? S_IXUSR : 0)
333 					| (fExecuteGroupCheckBox->Value() ? S_IXGRP :0)
334 					| (fExecuteOtherCheckBox->Value() ? S_IXOTH : 0));
335 
336 				BNode node(fModel->EntryRef());
337 
338 				if (node.InitCheck() == B_OK)
339 					node.SetPermissions(newPermissions);
340 				else {
341 					ModelChanged(fModel);
342 					beep();
343 				}
344 			}
345 			break;
346 
347 		case kNewOwnerEntered:
348 			if (fModel != NULL) {
349 				uid_t owner;
350 				if (sscanf(fOwnerTextControl->Text(), "%d", &owner) == 1) {
351 					BNode node(fModel->EntryRef());
352 					if (node.InitCheck() == B_OK)
353 						node.SetOwner(owner);
354 					else {
355 						ModelChanged(fModel);
356 						beep();
357 					}
358 				} else {
359 					ModelChanged(fModel);
360 					beep();
361 				}
362 			}
363 			break;
364 
365 		case kNewGroupEntered:
366 			if (fModel != NULL) {
367 				gid_t group;
368 				if (sscanf(fGroupTextControl->Text(), "%d", &group) == 1) {
369 					BNode node(fModel->EntryRef());
370 					if (node.InitCheck() == B_OK)
371 						node.SetGroup(group);
372 					else {
373 						ModelChanged(fModel);
374 						beep();
375 					}
376 				} else {
377 					ModelChanged(fModel);
378 					beep();
379 				}
380 			}
381 			break;
382 
383 		default:
384 			_inherited::MessageReceived(message);
385 			break;
386 	}
387 }
388 
389 
390 void
391 FilePermissionsView::AttachedToWindow()
392 {
393 	fReadUserCheckBox->SetTarget(this);
394 	fReadGroupCheckBox->SetTarget(this);
395 	fReadOtherCheckBox->SetTarget(this);
396 	fWriteUserCheckBox->SetTarget(this);
397 	fWriteGroupCheckBox->SetTarget(this);
398 	fWriteOtherCheckBox->SetTarget(this);
399 	fExecuteUserCheckBox->SetTarget(this);
400 	fExecuteGroupCheckBox->SetTarget(this);
401 	fExecuteOtherCheckBox->SetTarget(this);
402 
403 	fOwnerTextControl->SetTarget(this);
404 	fGroupTextControl->SetTarget(this);
405 }
406