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(¤tFont); 65 66 currentFont.SetRotation(57); 67 SetFont(¤tFont); 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(¤tFont); 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