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 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