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_VERTICAL); 183 184 SetLayout(groupLayout); 185 186 BLayoutBuilder::Group<>(groupLayout) 187 .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING, 0.0f) 188 .SetInsets(B_USE_DEFAULT_SPACING) 189 .AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING) 190 .Add(ownerRightLabel, 1, 0) 191 .Add(groupRightLabel, 2, 0) 192 .Add(otherRightLabel, 3, 0) 193 .Add(readLabel, 0, 1) 194 .Add(writeLabel, 0, 2) 195 .Add(executeLabel, 0, 3) 196 .Add(fReadUserCheckBox, 1, 1) 197 .Add(fReadGroupCheckBox, 2, 1) 198 .Add(fReadOtherCheckBox, 3, 1) 199 .Add(fWriteUserCheckBox, 1, 2) 200 .Add(fWriteGroupCheckBox, 2, 2) 201 .Add(fWriteOtherCheckBox, 3, 2) 202 .Add(fExecuteUserCheckBox, 1, 3) 203 .Add(fExecuteGroupCheckBox, 2, 3) 204 .Add(fExecuteOtherCheckBox, 3, 3) 205 .AddGlue(0, 4) 206 .End() 207 .AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING) 208 .AddGlue(0, 0) 209 .AddTextControl(fOwnerTextControl, 0, 1) 210 .AddTextControl(fGroupTextControl, 0, 2) 211 .End() 212 .AddGlue() 213 .End() 214 .AddGlue(); 215 216 ModelChanged(model); 217 } 218 219 220 void 221 FilePermissionsView::ModelChanged(Model* model) 222 { 223 fModel = model; 224 225 bool hideCheckBoxes = false; 226 uid_t nodeOwner = 0; 227 gid_t nodeGroup = 0; 228 mode_t perms = 0; 229 230 if (fModel != NULL) { 231 BNode node(fModel->EntryRef()); 232 233 if (node.InitCheck() == B_OK) { 234 if (fReadUserCheckBox->IsHidden()) { 235 fReadUserCheckBox->Show(); 236 fReadGroupCheckBox->Show(); 237 fReadOtherCheckBox->Show(); 238 fWriteUserCheckBox->Show(); 239 fWriteGroupCheckBox->Show(); 240 fWriteOtherCheckBox->Show(); 241 fExecuteUserCheckBox->Show(); 242 fExecuteGroupCheckBox->Show(); 243 fExecuteOtherCheckBox->Show(); 244 } 245 246 if (node.GetPermissions(&perms) == B_OK) { 247 fReadUserCheckBox->SetValue((int32)(perms & S_IRUSR)); 248 fReadGroupCheckBox->SetValue((int32)(perms & S_IRGRP)); 249 fReadOtherCheckBox->SetValue((int32)(perms & S_IROTH)); 250 fWriteUserCheckBox->SetValue((int32)(perms & S_IWUSR)); 251 fWriteGroupCheckBox->SetValue((int32)(perms & S_IWGRP)); 252 fWriteOtherCheckBox->SetValue((int32)(perms & S_IWOTH)); 253 fExecuteUserCheckBox->SetValue((int32)(perms & S_IXUSR)); 254 fExecuteGroupCheckBox->SetValue((int32)(perms & S_IXGRP)); 255 fExecuteOtherCheckBox->SetValue((int32)(perms & S_IXOTH)); 256 } else 257 hideCheckBoxes = true; 258 259 if (node.GetOwner(&nodeOwner) == B_OK) { 260 BString user; 261 if (nodeOwner == 0) 262 if (getenv("USER") != NULL) 263 user << getenv("USER"); 264 else 265 user << "root"; 266 else 267 user << nodeOwner; 268 fOwnerTextControl->SetText(user.String()); 269 } else 270 fOwnerTextControl->SetText(B_TRANSLATE("Unknown")); 271 272 if (node.GetGroup(&nodeGroup) == B_OK) { 273 BString group; 274 if (nodeGroup == 0) 275 if (getenv("GROUP") != NULL) 276 group << getenv("GROUP"); 277 else 278 group << "0"; 279 else 280 group << nodeGroup; 281 fGroupTextControl->SetText(group.String()); 282 } else 283 fGroupTextControl->SetText(B_TRANSLATE("Unknown")); 284 285 // Unless we're root, only allow the owner to transfer the 286 // ownership, i.e. disable text controls if uid:s doesn't match: 287 thread_id thisThread = find_thread(NULL); 288 thread_info threadInfo; 289 get_thread_info(thisThread, &threadInfo); 290 team_info teamInfo; 291 get_team_info(threadInfo.team, &teamInfo); 292 if (teamInfo.uid != 0 && nodeOwner != teamInfo.uid) { 293 fOwnerTextControl->SetEnabled(false); 294 fGroupTextControl->SetEnabled(false); 295 } else { 296 fOwnerTextControl->SetEnabled(true); 297 fGroupTextControl->SetEnabled(true); 298 } 299 } else 300 hideCheckBoxes = true; 301 } else 302 hideCheckBoxes = true; 303 304 if (hideCheckBoxes) { 305 fReadUserCheckBox->Hide(); 306 fReadGroupCheckBox->Hide(); 307 fReadOtherCheckBox->Hide(); 308 fWriteUserCheckBox->Hide(); 309 fWriteGroupCheckBox->Hide(); 310 fWriteOtherCheckBox->Hide(); 311 fExecuteUserCheckBox->Hide(); 312 fExecuteGroupCheckBox->Hide(); 313 fExecuteOtherCheckBox->Hide(); 314 } 315 } 316 317 318 void 319 FilePermissionsView::MessageReceived(BMessage* message) 320 { 321 switch(message->what) { 322 case kPermissionsChanged: 323 if (fModel != NULL) { 324 mode_t newPermissions = 0; 325 newPermissions 326 = (mode_t)((fReadUserCheckBox->Value() ? S_IRUSR : 0) 327 | (fReadGroupCheckBox->Value() ? S_IRGRP : 0) 328 | (fReadOtherCheckBox->Value() ? S_IROTH : 0) 329 330 | (fWriteUserCheckBox->Value() ? S_IWUSR : 0) 331 | (fWriteGroupCheckBox->Value() ? S_IWGRP : 0) 332 | (fWriteOtherCheckBox->Value() ? S_IWOTH : 0) 333 334 | (fExecuteUserCheckBox->Value() ? S_IXUSR : 0) 335 | (fExecuteGroupCheckBox->Value() ? S_IXGRP :0) 336 | (fExecuteOtherCheckBox->Value() ? S_IXOTH : 0)); 337 338 BNode node(fModel->EntryRef()); 339 340 if (node.InitCheck() == B_OK) 341 node.SetPermissions(newPermissions); 342 else { 343 ModelChanged(fModel); 344 beep(); 345 } 346 } 347 break; 348 349 case kNewOwnerEntered: 350 if (fModel != NULL) { 351 uid_t owner; 352 if (sscanf(fOwnerTextControl->Text(), "%d", &owner) == 1) { 353 BNode node(fModel->EntryRef()); 354 if (node.InitCheck() == B_OK) 355 node.SetOwner(owner); 356 else { 357 ModelChanged(fModel); 358 beep(); 359 } 360 } else { 361 ModelChanged(fModel); 362 beep(); 363 } 364 } 365 break; 366 367 case kNewGroupEntered: 368 if (fModel != NULL) { 369 gid_t group; 370 if (sscanf(fGroupTextControl->Text(), "%d", &group) == 1) { 371 BNode node(fModel->EntryRef()); 372 if (node.InitCheck() == B_OK) 373 node.SetGroup(group); 374 else { 375 ModelChanged(fModel); 376 beep(); 377 } 378 } else { 379 ModelChanged(fModel); 380 beep(); 381 } 382 } 383 break; 384 385 default: 386 _inherited::MessageReceived(message); 387 break; 388 } 389 } 390 391 392 void 393 FilePermissionsView::AttachedToWindow() 394 { 395 fReadUserCheckBox->SetTarget(this); 396 fReadGroupCheckBox->SetTarget(this); 397 fReadOtherCheckBox->SetTarget(this); 398 fWriteUserCheckBox->SetTarget(this); 399 fWriteGroupCheckBox->SetTarget(this); 400 fWriteOtherCheckBox->SetTarget(this); 401 fExecuteUserCheckBox->SetTarget(this); 402 fExecuteGroupCheckBox->SetTarget(this); 403 fExecuteOtherCheckBox->SetTarget(this); 404 405 fOwnerTextControl->SetTarget(this); 406 fGroupTextControl->SetTarget(this); 407 } 408