1/* 2Open Tracker License 3 4Terms and Conditions 5 6Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a copy of 9this software and associated documentation files (the "Software"), to deal in 10the Software without restriction, including without limitation the rights to 11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12of the Software, and to permit persons to whom the Software is furnished to do 13so, subject to the following conditions: 14 15The above copyright notice and this permission notice applies to all licensees 16and shall be included in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of Be Incorporated shall not be 26used in advertising or otherwise to promote the sale, use or other dealings in 27this Software without prior written authorization from Be Incorporated. 28 29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30of Be Incorporated in the United States and other countries. Other brand product 31names are registered trademarks or trademarks of their respective holders. 32All 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 52const uint32 kPermissionsChanged = 'prch'; 53const uint32 kNewOwnerEntered = 'nwow'; 54const uint32 kNewGroupEntered = 'nwgr'; 55 56 57class RotatedStringView: public BStringView 58{ 59public: 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 102private: 103 BSize fExplicitSize; 104}; 105 106 107// #pragma mark - FilePermissionsView 108 109 110FilePermissionsView::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 220void 221FilePermissionsView::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 318void 319FilePermissionsView::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 392void 393FilePermissionsView::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