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 <stdio.h> 39 #include <stdlib.h> 40 41 #include <Beep.h> 42 #include <Catalog.h> 43 #include <Locale.h> 44 45 46 #undef B_TRANSLATION_CONTEXT 47 #define B_TRANSLATION_CONTEXT "FilePermissionsView" 48 49 50 const uint32 kPermissionsChanged = 'prch'; 51 const uint32 kNewOwnerEntered = 'nwow'; 52 const uint32 kNewGroupEntered = 'nwgr'; 53 54 55 class RotatedStringView: public BStringView 56 { 57 public: 58 RotatedStringView(BRect r, const char* name, const char* label) 59 : BStringView(r, name, label) 60 { 61 } 62 63 void Draw(BRect invalidate) 64 { 65 RotateBy(-M_PI / 5); 66 TranslateBy(0, Bounds().Height() / 3); 67 BStringView::Draw(invalidate); 68 } 69 }; 70 71 72 // #pragma mark - FilePermissionsView 73 74 75 FilePermissionsView::FilePermissionsView(BRect rect, Model* model) 76 : 77 BView(rect, B_TRANSLATE("Permissions"), B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW), 78 fModel(model) 79 { 80 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 81 82 // Constants for the column labels: "User", "Group" and "Other". 83 const float kColumnLabelMiddle = 77, kColumnLabelTop = 0, 84 kColumnLabelSpacing = 37, kColumnLabelBottom = 39, 85 kColumnLabelWidth = 80, kAttribFontHeight = 10; 86 87 BStringView* strView; 88 89 strView = new RotatedStringView( 90 BRect(kColumnLabelMiddle - kColumnLabelWidth / 2, 91 kColumnLabelTop, 92 kColumnLabelMiddle + kColumnLabelWidth / 2, 93 kColumnLabelBottom), 94 "", B_TRANSLATE("Owner")); 95 AddChild(strView); 96 strView->SetFontSize(kAttribFontHeight); 97 98 strView = new RotatedStringView( 99 BRect(kColumnLabelMiddle - kColumnLabelWidth / 2 100 + kColumnLabelSpacing, 101 kColumnLabelTop, 102 kColumnLabelMiddle + kColumnLabelWidth / 2 + kColumnLabelSpacing, 103 kColumnLabelBottom), 104 "", B_TRANSLATE("Group")); 105 AddChild(strView); 106 strView->SetFontSize(kAttribFontHeight); 107 108 strView = new RotatedStringView( 109 BRect(kColumnLabelMiddle - kColumnLabelWidth / 2 110 + 2 * kColumnLabelSpacing, 111 kColumnLabelTop, 112 kColumnLabelMiddle + kColumnLabelWidth / 2 113 + 2 * kColumnLabelSpacing, 114 kColumnLabelBottom), 115 "", B_TRANSLATE("Other")); 116 AddChild(strView); 117 strView->SetFontSize(kAttribFontHeight); 118 119 // Constants for the row labels: "Read", "Write" and "Execute". 120 const float kRowLabelLeft = 10, kRowLabelTop = kColumnLabelBottom + 5, 121 kRowLabelVerticalSpacing = 18, kRowLabelRight = kColumnLabelMiddle 122 - kColumnLabelSpacing / 2 - 5, kRowLabelHeight = 14; 123 124 strView = new BStringView(BRect(kRowLabelLeft, kRowLabelTop, 125 kRowLabelRight, kRowLabelTop + kRowLabelHeight), 126 "", B_TRANSLATE("Read")); 127 AddChild(strView); 128 strView->SetAlignment(B_ALIGN_RIGHT); 129 strView->SetFontSize(kAttribFontHeight); 130 131 strView = new BStringView(BRect(kRowLabelLeft, kRowLabelTop 132 + kRowLabelVerticalSpacing, kRowLabelRight, kRowLabelTop 133 + kRowLabelVerticalSpacing + kRowLabelHeight), 134 "", B_TRANSLATE("Write")); 135 AddChild(strView); 136 strView->SetAlignment(B_ALIGN_RIGHT); 137 strView->SetFontSize(kAttribFontHeight); 138 139 strView = new BStringView(BRect(kRowLabelLeft, kRowLabelTop 140 + 2 * kRowLabelVerticalSpacing, kRowLabelRight, kRowLabelTop 141 + 2 * kRowLabelVerticalSpacing + kRowLabelHeight), 142 "", B_TRANSLATE("Execute")); 143 AddChild(strView); 144 strView->SetAlignment(B_ALIGN_RIGHT); 145 strView->SetFontSize(kAttribFontHeight); 146 147 // Constants for the 3x3 check box array. 148 const float kLeftMargin = kRowLabelRight + 5, 149 kTopMargin = kRowLabelTop - 2, 150 kHorizontalSpacing = kColumnLabelSpacing, 151 kVerticalSpacing = kRowLabelVerticalSpacing, 152 kCheckBoxWidth = 18, kCheckBoxHeight = 18; 153 154 BCheckBox** checkBoxArray[3][3] = { 155 { 156 &fReadUserCheckBox, 157 &fReadGroupCheckBox, 158 &fReadOtherCheckBox 159 }, 160 { 161 &fWriteUserCheckBox, 162 &fWriteGroupCheckBox, 163 &fWriteOtherCheckBox 164 }, 165 { 166 &fExecuteUserCheckBox, 167 &fExecuteGroupCheckBox, 168 &fExecuteOtherCheckBox 169 } 170 }; 171 172 for (int32 x = 0; x < 3; x++) { 173 for (int32 y = 0; y < 3; y++) { 174 *checkBoxArray[y][x] = 175 new BCheckBox(BRect(kLeftMargin + kHorizontalSpacing * x, 176 kTopMargin + kVerticalSpacing * y, 177 kLeftMargin + kHorizontalSpacing * x + kCheckBoxWidth, 178 kTopMargin + kVerticalSpacing * y + kCheckBoxHeight), 179 "", "", new BMessage(kPermissionsChanged)); 180 AddChild(*checkBoxArray[y][x]); 181 } 182 } 183 184 const float kTextControlLeft = 170, kTextControlRight = 270, 185 kTextControlTop = kRowLabelTop - 29, 186 kTextControlHeight = 14, kTextControlSpacing = 16; 187 188 strView = new BStringView(BRect(kTextControlLeft, kTextControlTop, 189 kTextControlRight, kTextControlTop + kTextControlHeight), "", 190 B_TRANSLATE("Owner")); 191 strView->SetAlignment(B_ALIGN_CENTER); 192 strView->SetFontSize(kAttribFontHeight); 193 AddChild(strView); 194 195 fOwnerTextControl = new BTextControl( 196 BRect(kTextControlLeft, 197 kTextControlTop - 2 + kTextControlSpacing, 198 kTextControlRight, 199 kTextControlTop + kTextControlHeight - 2 + kTextControlSpacing), 200 "", "", "", new BMessage(kNewOwnerEntered)); 201 fOwnerTextControl->SetDivider(0); 202 AddChild(fOwnerTextControl); 203 204 strView = new BStringView(BRect(kTextControlLeft, 205 kTextControlTop + 11 + 2 * kTextControlSpacing, 206 kTextControlRight, 207 kTextControlTop + 11 + 2 * kTextControlSpacing 208 + kTextControlHeight), 209 "", B_TRANSLATE("Group")); 210 strView->SetAlignment(B_ALIGN_CENTER); 211 strView->SetFontSize(kAttribFontHeight); 212 AddChild(strView); 213 214 fGroupTextControl = new BTextControl(BRect(kTextControlLeft, 215 kTextControlTop + 10 + 3 * kTextControlSpacing, 216 kTextControlRight, 217 kTextControlTop + 10 + 3 * kTextControlSpacing + kTextControlHeight), 218 "", "", "", new BMessage(kNewGroupEntered)); 219 fGroupTextControl->SetDivider(0); 220 AddChild(fGroupTextControl); 221 222 ModelChanged(model); 223 } 224 225 226 void 227 FilePermissionsView::ModelChanged(Model* model) 228 { 229 fModel = model; 230 231 bool hideCheckBoxes = false; 232 uid_t nodeOwner = 0; 233 gid_t nodeGroup = 0; 234 mode_t perms = 0; 235 236 if (fModel != NULL) { 237 BNode node(fModel->EntryRef()); 238 239 if (node.InitCheck() == B_OK) { 240 if (fReadUserCheckBox->IsHidden()) { 241 fReadUserCheckBox->Show(); 242 fReadGroupCheckBox->Show(); 243 fReadOtherCheckBox->Show(); 244 fWriteUserCheckBox->Show(); 245 fWriteGroupCheckBox->Show(); 246 fWriteOtherCheckBox->Show(); 247 fExecuteUserCheckBox->Show(); 248 fExecuteGroupCheckBox->Show(); 249 fExecuteOtherCheckBox->Show(); 250 } 251 252 if (node.GetPermissions(&perms) == B_OK) { 253 fReadUserCheckBox->SetValue((int32)(perms & S_IRUSR)); 254 fReadGroupCheckBox->SetValue((int32)(perms & S_IRGRP)); 255 fReadOtherCheckBox->SetValue((int32)(perms & S_IROTH)); 256 fWriteUserCheckBox->SetValue((int32)(perms & S_IWUSR)); 257 fWriteGroupCheckBox->SetValue((int32)(perms & S_IWGRP)); 258 fWriteOtherCheckBox->SetValue((int32)(perms & S_IWOTH)); 259 fExecuteUserCheckBox->SetValue((int32)(perms & S_IXUSR)); 260 fExecuteGroupCheckBox->SetValue((int32)(perms & S_IXGRP)); 261 fExecuteOtherCheckBox->SetValue((int32)(perms & S_IXOTH)); 262 } else 263 hideCheckBoxes = true; 264 265 if (node.GetOwner(&nodeOwner) == B_OK) { 266 BString user; 267 if (nodeOwner == 0) 268 if (getenv("USER") != NULL) 269 user << getenv("USER"); 270 else 271 user << "root"; 272 else 273 user << nodeOwner; 274 fOwnerTextControl->SetText(user.String()); 275 } else 276 fOwnerTextControl->SetText(B_TRANSLATE("Unknown")); 277 278 if (node.GetGroup(&nodeGroup) == B_OK) { 279 BString group; 280 if (nodeGroup == 0) 281 if (getenv("GROUP") != NULL) 282 group << getenv("GROUP"); 283 else 284 group << "0"; 285 else 286 group << nodeGroup; 287 fGroupTextControl->SetText(group.String()); 288 } else 289 fGroupTextControl->SetText(B_TRANSLATE("Unknown")); 290 291 // Unless we're root, only allow the owner to transfer the 292 // ownership, i.e. disable text controls if uid:s doesn't match: 293 thread_id thisThread = find_thread(NULL); 294 thread_info threadInfo; 295 get_thread_info(thisThread, &threadInfo); 296 team_info teamInfo; 297 get_team_info(threadInfo.team, &teamInfo); 298 if (teamInfo.uid != 0 && nodeOwner != teamInfo.uid) { 299 fOwnerTextControl->SetEnabled(false); 300 fGroupTextControl->SetEnabled(false); 301 } else { 302 fOwnerTextControl->SetEnabled(true); 303 fGroupTextControl->SetEnabled(true); 304 } 305 } else 306 hideCheckBoxes = true; 307 } else 308 hideCheckBoxes = true; 309 310 if (hideCheckBoxes) { 311 fReadUserCheckBox->Hide(); 312 fReadGroupCheckBox->Hide(); 313 fReadOtherCheckBox->Hide(); 314 fWriteUserCheckBox->Hide(); 315 fWriteGroupCheckBox->Hide(); 316 fWriteOtherCheckBox->Hide(); 317 fExecuteUserCheckBox->Hide(); 318 fExecuteGroupCheckBox->Hide(); 319 fExecuteOtherCheckBox->Hide(); 320 } 321 } 322 323 324 void 325 FilePermissionsView::MessageReceived(BMessage* message) 326 { 327 switch(message->what) { 328 case kPermissionsChanged: 329 if (fModel != NULL) { 330 mode_t newPermissions = 0; 331 newPermissions 332 = (mode_t)((fReadUserCheckBox->Value() ? S_IRUSR : 0) 333 | (fReadGroupCheckBox->Value() ? S_IRGRP : 0) 334 | (fReadOtherCheckBox->Value() ? S_IROTH : 0) 335 336 | (fWriteUserCheckBox->Value() ? S_IWUSR : 0) 337 | (fWriteGroupCheckBox->Value() ? S_IWGRP : 0) 338 | (fWriteOtherCheckBox->Value() ? S_IWOTH : 0) 339 340 | (fExecuteUserCheckBox->Value() ? S_IXUSR : 0) 341 | (fExecuteGroupCheckBox->Value() ? S_IXGRP :0) 342 | (fExecuteOtherCheckBox->Value() ? S_IXOTH : 0)); 343 344 BNode node(fModel->EntryRef()); 345 346 if (node.InitCheck() == B_OK) 347 node.SetPermissions(newPermissions); 348 else { 349 ModelChanged(fModel); 350 beep(); 351 } 352 } 353 break; 354 355 case kNewOwnerEntered: 356 if (fModel != NULL) { 357 uid_t owner; 358 if (sscanf(fOwnerTextControl->Text(), "%d", &owner) == 1) { 359 BNode node(fModel->EntryRef()); 360 if (node.InitCheck() == B_OK) 361 node.SetOwner(owner); 362 else { 363 ModelChanged(fModel); 364 beep(); 365 } 366 } else { 367 ModelChanged(fModel); 368 beep(); 369 } 370 } 371 break; 372 373 case kNewGroupEntered: 374 if (fModel != NULL) { 375 gid_t group; 376 if (sscanf(fGroupTextControl->Text(), "%d", &group) == 1) { 377 BNode node(fModel->EntryRef()); 378 if (node.InitCheck() == B_OK) 379 node.SetGroup(group); 380 else { 381 ModelChanged(fModel); 382 beep(); 383 } 384 } else { 385 ModelChanged(fModel); 386 beep(); 387 } 388 } 389 break; 390 391 default: 392 _inherited::MessageReceived(message); 393 break; 394 } 395 } 396 397 398 void 399 FilePermissionsView::AttachedToWindow() 400 { 401 fReadUserCheckBox->SetTarget(this); 402 fReadGroupCheckBox->SetTarget(this); 403 fReadOtherCheckBox->SetTarget(this); 404 fWriteUserCheckBox->SetTarget(this); 405 fWriteGroupCheckBox->SetTarget(this); 406 fWriteOtherCheckBox->SetTarget(this); 407 fExecuteUserCheckBox->SetTarget(this); 408 fExecuteGroupCheckBox->SetTarget(this); 409 fExecuteOtherCheckBox->SetTarget(this); 410 411 fOwnerTextControl->SetTarget(this); 412 fGroupTextControl->SetTarget(this); 413 } 414