xref: /haiku/src/kits/tracker/infowindow/FilePermissionsView.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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 	SetHighUIColor(B_PANEL_TEXT_COLOR);
117 
118 	RotatedStringView* ownerRightLabel = new RotatedStringView("",
119 		B_TRANSLATE("Owner"));
120 	RotatedStringView* groupRightLabel = new RotatedStringView("",
121 		B_TRANSLATE("Group"));
122 	RotatedStringView* otherRightLabel = new RotatedStringView("",
123 		B_TRANSLATE("Other"));
124 
125 	// Get the largest inclined area of the three
126 	BSize ownerRightLabelSize, groupRightLabelSize, maxSize;
127 
128 	ownerRightLabelSize = ownerRightLabel->ExplicitSize();
129 	groupRightLabelSize = groupRightLabel->ExplicitSize();
130 
131 	maxSize.width = std::max(ownerRightLabelSize.width,
132 		groupRightLabelSize.width);
133 	maxSize.width = std::max(maxSize.width,
134 		otherRightLabel->ExplicitSize().width);
135 
136 	maxSize.height = std::max(ownerRightLabel->ExplicitSize().height,
137 		groupRightLabel->ExplicitSize().height);
138 	maxSize.height = std::max(maxSize.height,
139 		otherRightLabel->ExplicitSize().height);
140 
141 
142 	// Set all the component with this size
143 	ownerRightLabel->SetExplicitSize(maxSize);
144 	groupRightLabel->SetExplicitSize(maxSize);
145 	otherRightLabel->SetExplicitSize(maxSize);
146 
147 	BStringView* readLabel = new BStringView("", B_TRANSLATE("Read"));
148 	readLabel->SetAlignment(B_ALIGN_RIGHT);
149 
150 	BStringView* writeLabel = new BStringView("", B_TRANSLATE("Write"));
151 	writeLabel->SetAlignment(B_ALIGN_RIGHT);
152 
153 	BStringView* executeLabel = new BStringView("", B_TRANSLATE("Execute"));
154 	executeLabel->SetAlignment(B_ALIGN_RIGHT);
155 
156 	// Creating checkbox
157 	fReadUserCheckBox = new BCheckBox("", "",
158 		new BMessage(kPermissionsChanged));
159 	fReadGroupCheckBox = new BCheckBox("", "",
160 		new BMessage(kPermissionsChanged));
161 	fReadOtherCheckBox = new BCheckBox("", "",
162 		new BMessage(kPermissionsChanged));
163 
164 	fWriteUserCheckBox = new BCheckBox("", "",
165 		new BMessage(kPermissionsChanged));
166 	fWriteGroupCheckBox = new BCheckBox("", "",
167 		new BMessage(kPermissionsChanged));
168 	fWriteOtherCheckBox = new BCheckBox("", "",
169 		new BMessage(kPermissionsChanged));
170 
171 	fExecuteUserCheckBox = new BCheckBox("", "",
172 		new BMessage(kPermissionsChanged));
173 	fExecuteGroupCheckBox = new BCheckBox("", "",
174 		new BMessage(kPermissionsChanged));
175 	fExecuteOtherCheckBox = new BCheckBox("", "",
176 		new BMessage(kPermissionsChanged));
177 
178 	fOwnerTextControl = new BTextControl("", B_TRANSLATE("Owner"), "",
179 		new BMessage(kNewOwnerEntered));
180 	fGroupTextControl = new BTextControl("", B_TRANSLATE("Group"), "",
181 		new BMessage(kNewGroupEntered));
182 
183 	BGroupLayout* groupLayout = new BGroupLayout(B_VERTICAL);
184 
185 	SetLayout(groupLayout);
186 
187 	BLayoutBuilder::Group<>(groupLayout)
188 		.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 0.0f)
189 			.SetInsets(B_USE_DEFAULT_SPACING)
190 			.AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
191 				.Add(ownerRightLabel, 1, 0)
192 				.Add(groupRightLabel, 2, 0)
193 				.Add(otherRightLabel, 3, 0)
194 				.Add(readLabel, 0, 1)
195 				.Add(writeLabel, 0, 2)
196 				.Add(executeLabel, 0, 3)
197 				.Add(fReadUserCheckBox, 1, 1)
198 				.Add(fReadGroupCheckBox, 2, 1)
199 				.Add(fReadOtherCheckBox, 3, 1)
200 				.Add(fWriteUserCheckBox, 1, 2)
201 				.Add(fWriteGroupCheckBox, 2, 2)
202 				.Add(fWriteOtherCheckBox, 3, 2)
203 				.Add(fExecuteUserCheckBox, 1, 3)
204 				.Add(fExecuteGroupCheckBox, 2, 3)
205 				.Add(fExecuteOtherCheckBox, 3, 3)
206 				.AddGlue(0, 4)
207 			.End()
208 			.AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
209 				.AddGlue(0, 0)
210 				.AddTextControl(fOwnerTextControl, 0, 1)
211 				.AddTextControl(fGroupTextControl, 0, 2)
212 			.End()
213 			.AddGlue()
214 		.End()
215 		.AddGlue();
216 
217 	ModelChanged(model);
218 }
219 
220 
221 void
222 FilePermissionsView::ModelChanged(Model* model)
223 {
224 	fModel = model;
225 
226 	bool hideCheckBoxes = false;
227 	uid_t nodeOwner = 0;
228 	gid_t nodeGroup = 0;
229 	mode_t perms = 0;
230 
231 	if (fModel != NULL) {
232 		BNode node(fModel->EntryRef());
233 
234 		if (node.InitCheck() == B_OK) {
235 			if (fReadUserCheckBox->IsHidden()) {
236 				fReadUserCheckBox->Show();
237 				fReadGroupCheckBox->Show();
238 				fReadOtherCheckBox->Show();
239 				fWriteUserCheckBox->Show();
240 				fWriteGroupCheckBox->Show();
241 				fWriteOtherCheckBox->Show();
242 				fExecuteUserCheckBox->Show();
243 				fExecuteGroupCheckBox->Show();
244 				fExecuteOtherCheckBox->Show();
245 			}
246 
247 			if (node.GetPermissions(&perms) == B_OK) {
248 				fReadUserCheckBox->SetValue((int32)(perms & S_IRUSR));
249 				fReadGroupCheckBox->SetValue((int32)(perms & S_IRGRP));
250 				fReadOtherCheckBox->SetValue((int32)(perms & S_IROTH));
251 				fWriteUserCheckBox->SetValue((int32)(perms & S_IWUSR));
252 				fWriteGroupCheckBox->SetValue((int32)(perms & S_IWGRP));
253 				fWriteOtherCheckBox->SetValue((int32)(perms & S_IWOTH));
254 				fExecuteUserCheckBox->SetValue((int32)(perms & S_IXUSR));
255 				fExecuteGroupCheckBox->SetValue((int32)(perms & S_IXGRP));
256 				fExecuteOtherCheckBox->SetValue((int32)(perms & S_IXOTH));
257 			} else
258 				hideCheckBoxes = true;
259 
260 			if (node.GetOwner(&nodeOwner) == B_OK) {
261 				BString user;
262 				if (nodeOwner == 0)
263 					if (getenv("USER") != NULL)
264 						user << getenv("USER");
265 					else
266 						user << "root";
267 				else
268 					user << nodeOwner;
269 				fOwnerTextControl->SetText(user.String());
270 			} else
271 				fOwnerTextControl->SetText(B_TRANSLATE("Unknown"));
272 
273 			if (node.GetGroup(&nodeGroup) == B_OK) {
274 				BString group;
275 				if (nodeGroup == 0)
276 					if (getenv("GROUP") != NULL)
277 						group << getenv("GROUP");
278 					else
279 						group << "0";
280 				else
281 					group << nodeGroup;
282 				fGroupTextControl->SetText(group.String());
283 			} else
284 				fGroupTextControl->SetText(B_TRANSLATE("Unknown"));
285 
286 			// Unless we're root, only allow the owner to transfer the
287 			// ownership, i.e. disable text controls if uid:s doesn't match:
288 			thread_id thisThread = find_thread(NULL);
289 			thread_info threadInfo;
290 			get_thread_info(thisThread, &threadInfo);
291 			team_info teamInfo;
292 			get_team_info(threadInfo.team, &teamInfo);
293 			if (teamInfo.uid != 0 && nodeOwner != teamInfo.uid) {
294 				fOwnerTextControl->SetEnabled(false);
295 				fGroupTextControl->SetEnabled(false);
296 			} else {
297 				fOwnerTextControl->SetEnabled(true);
298 				fGroupTextControl->SetEnabled(true);
299 			}
300 		} else
301 			hideCheckBoxes = true;
302 	} else
303 		hideCheckBoxes = true;
304 
305 	if (hideCheckBoxes) {
306 		fReadUserCheckBox->Hide();
307 		fReadGroupCheckBox->Hide();
308 		fReadOtherCheckBox->Hide();
309 		fWriteUserCheckBox->Hide();
310 		fWriteGroupCheckBox->Hide();
311 		fWriteOtherCheckBox->Hide();
312 		fExecuteUserCheckBox->Hide();
313 		fExecuteGroupCheckBox->Hide();
314 		fExecuteOtherCheckBox->Hide();
315 	}
316 }
317 
318 
319 void
320 FilePermissionsView::MessageReceived(BMessage* message)
321 {
322 	switch(message->what) {
323 		case kPermissionsChanged:
324 			if (fModel != NULL) {
325 				mode_t newPermissions = 0;
326 				newPermissions
327 					= (mode_t)((fReadUserCheckBox->Value() ? S_IRUSR : 0)
328 					| (fReadGroupCheckBox->Value() ? S_IRGRP : 0)
329 					| (fReadOtherCheckBox->Value() ? S_IROTH : 0)
330 
331 					| (fWriteUserCheckBox->Value() ? S_IWUSR : 0)
332 					| (fWriteGroupCheckBox->Value() ? S_IWGRP : 0)
333 					| (fWriteOtherCheckBox->Value() ? S_IWOTH : 0)
334 
335 					| (fExecuteUserCheckBox->Value() ? S_IXUSR : 0)
336 					| (fExecuteGroupCheckBox->Value() ? S_IXGRP :0)
337 					| (fExecuteOtherCheckBox->Value() ? S_IXOTH : 0));
338 
339 				BNode node(fModel->EntryRef());
340 
341 				if (node.InitCheck() == B_OK)
342 					node.SetPermissions(newPermissions);
343 				else {
344 					ModelChanged(fModel);
345 					beep();
346 				}
347 			}
348 			break;
349 
350 		case kNewOwnerEntered:
351 			if (fModel != NULL) {
352 				uid_t owner;
353 				if (sscanf(fOwnerTextControl->Text(), "%d", &owner) == 1) {
354 					BNode node(fModel->EntryRef());
355 					if (node.InitCheck() == B_OK)
356 						node.SetOwner(owner);
357 					else {
358 						ModelChanged(fModel);
359 						beep();
360 					}
361 				} else {
362 					ModelChanged(fModel);
363 					beep();
364 				}
365 			}
366 			break;
367 
368 		case kNewGroupEntered:
369 			if (fModel != NULL) {
370 				gid_t group;
371 				if (sscanf(fGroupTextControl->Text(), "%d", &group) == 1) {
372 					BNode node(fModel->EntryRef());
373 					if (node.InitCheck() == B_OK)
374 						node.SetGroup(group);
375 					else {
376 						ModelChanged(fModel);
377 						beep();
378 					}
379 				} else {
380 					ModelChanged(fModel);
381 					beep();
382 				}
383 			}
384 			break;
385 
386 		default:
387 			_inherited::MessageReceived(message);
388 			break;
389 	}
390 }
391 
392 
393 void
394 FilePermissionsView::AttachedToWindow()
395 {
396 	fReadUserCheckBox->SetTarget(this);
397 	fReadGroupCheckBox->SetTarget(this);
398 	fReadOtherCheckBox->SetTarget(this);
399 	fWriteUserCheckBox->SetTarget(this);
400 	fWriteGroupCheckBox->SetTarget(this);
401 	fWriteOtherCheckBox->SetTarget(this);
402 	fExecuteUserCheckBox->SetTarget(this);
403 	fExecuteGroupCheckBox->SetTarget(this);
404 	fExecuteOtherCheckBox->SetTarget(this);
405 
406 	fOwnerTextControl->SetTarget(this);
407 	fGroupTextControl->SetTarget(this);
408 }
409