11exports . ls = function ( task , command , params ) {
22 ObjC . import ( 'Foundation' ) ;
3+ let includeAttributes = false ;
34 let output = { } ;
45 try {
56 let command_params = JSON . parse ( params ) ;
7+ if ( command_params [ "includeAttributes" ] ) {
8+ includeAttributes = command_params [ "includeAttributes" ] ;
9+ }
610 let fileManager = $ . NSFileManager . defaultManager ;
711 let error = Ref ( ) ;
812 let path = command_params [ 'path' ] ;
@@ -24,132 +28,147 @@ exports.ls = function(task, command, params){
2428 }
2529 output [ 'host' ] = ObjC . unwrap ( apfell . procInfo . hostName ) ;
2630 output [ 'update_deleted' ] = true ;
27- let attributes = ObjC . deepUnwrap ( fileManager . attributesOfItemAtPathError ( $ ( path ) , error ) ) ;
28- let time_attributes = ObjC . unwrap ( fileManager . attributesOfItemAtPathError ( $ ( path ) , error ) ) ;
29- if ( attributes !== undefined ) {
30- output [ 'is_file' ] = true ;
31- output [ "success" ] = true ;
32- output [ 'files' ] = [ ] ;
33- if ( attributes . hasOwnProperty ( 'NSFileType' ) && attributes [ 'NSFileType' ] === "NSFileTypeDirectory" ) {
34- let error = Ref ( ) ;
35- output [ 'is_file' ] = false ;
36- let files = ObjC . deepUnwrap ( fileManager . contentsOfDirectoryAtPathError ( $ ( path ) , error ) ) ;
37- if ( files !== undefined ) {
38- let files_data = [ ] ;
39- output [ 'success' ] = true ;
40- let sub_files = files ;
41- if ( path [ path . length - 1 ] !== "/" ) {
42- path = path + "/" ;
31+ let attributes = undefined ;
32+ let time_attributes = undefined ;
33+ let isDirectory = Ref ( ) ;
34+ let exists = fileManager . fileExistsAtPathIsDirectory ( $ ( path ) , isDirectory ) ;
35+ if ( exists ) {
36+ output [ 'is_file' ] = ! isDirectory [ 0 ] ;
37+ } else {
38+ return {
39+ "user_output" : path + " does not exist or is not accessible in the current context" ,
40+ "completed" : true ,
41+ "status" : "error"
42+ } ;
43+ }
44+ if ( includeAttributes ) {
45+ attributes = ObjC . deepUnwrap ( fileManager . attributesOfItemAtPathError ( $ ( path ) , error ) ) ;
46+ time_attributes = ObjC . unwrap ( fileManager . attributesOfItemAtPathError ( $ ( path ) , error ) ) ;
47+ }
48+ output [ "success" ] = true ;
49+ output [ 'files' ] = [ ] ;
50+ if ( isDirectory [ 0 ] ) {
51+ let error = Ref ( ) ;
52+ let files = ObjC . deepUnwrap ( fileManager . contentsOfDirectoryAtPathError ( $ ( path ) , error ) ) ;
53+ if ( files !== undefined ) {
54+ let files_data = [ ] ;
55+ output [ 'success' ] = true ;
56+ let sub_files = files ;
57+ if ( path [ path . length - 1 ] !== "/" ) {
58+ path = path + "/" ;
59+ }
60+ for ( let i = 0 ; i < sub_files . length ; i ++ ) {
61+ let attr = undefined ;
62+ let time_attr = undefined ;
63+ if ( includeAttributes ) {
64+ attr = ObjC . deepUnwrap ( fileManager . attributesOfItemAtPathError ( $ ( path + sub_files [ i ] ) , error ) ) ;
65+ time_attr = ObjC . unwrap ( fileManager . attributesOfItemAtPathError ( $ ( path + sub_files [ i ] ) , error ) ) ;
4366 }
44- for ( let i = 0 ; i < sub_files . length ; i ++ ) {
45- let attr = ObjC . deepUnwrap ( fileManager . attributesOfItemAtPathError ( $ ( path + sub_files [ i ] ) , error ) ) ;
46- let time_attr = ObjC . unwrap ( fileManager . attributesOfItemAtPathError ( $ ( path + sub_files [ i ] ) , error ) ) ;
47- let file_add = { } ;
48- file_add [ 'name' ] = sub_files [ i ] ;
67+ let file_add = { } ;
68+ file_add [ 'name' ] = sub_files [ i ] ;
69+ if ( includeAttributes ) {
4970 let plistPerms = ObjC . unwrap ( fileManager . attributesOfItemAtPathError ( $ ( path + sub_files [ i ] ) , $ ( ) ) ) ;
50- if ( plistPerms !== undefined && plistPerms [ 'NSFileExtendedAttributes' ] !== undefined ) {
71+ if ( plistPerms !== undefined && plistPerms [ 'NSFileExtendedAttributes' ] !== undefined ) {
5172 let extended = { } ;
5273 let perms = plistPerms [ 'NSFileExtendedAttributes' ] . js ;
53- for ( let j in perms ) {
74+ for ( let j in perms ) {
5475 extended [ j ] = perms [ j ] . base64EncodedStringWithOptions ( 0 ) . js ;
5576 }
5677 file_add [ 'permissions' ] = extended ;
57- } else {
78+ } else {
5879 file_add [ 'permissions' ] = { } ;
5980 }
60- if ( attr !== undefined ) {
61- file_add [ 'is_file' ] = attr [ 'NSFileType' ] !== "NSFileTypeDirectory" ;
62- file_add [ 'size' ] = attr [ 'NSFileSize' ] ;
63- let nsposix = attr [ 'NSFilePosixPermissions' ] ;
64- // we need to fix this mess to actually be real permission bits that make sense
65- file_add [ 'permissions' ] [ 'posix' ] = ( ( nsposix >> 6 ) & 0x7 ) . toString ( ) + ( ( nsposix >> 3 ) & 0x7 ) . toString ( ) + ( nsposix & 0x7 ) . toString ( ) ;
66- file_add [ 'permissions' ] [ 'owner' ] = attr [ 'NSFileOwnerAccountName' ] + "(" + attr [ 'NSFileOwnerAccountID' ] + ")" ;
67- file_add [ 'permissions' ] [ 'group' ] = attr [ 'NSFileGroupOwnerAccountName' ] + "(" + attr [ 'NSFileGroupOwnerAccountID' ] + ")" ;
68- file_add [ 'permissions' ] [ 'hidden' ] = attr [ 'NSFileExtensionAttribute' ] === true ;
69- file_add [ 'permissions' ] [ 'create_time' ] = Math . floor ( Math . trunc ( time_attr [ 'NSFileCreationDate' ] ?. timeIntervalSince1970 * 1000 || 0 ) ) ;
70- if ( file_add [ 'permissions' ] [ 'create_time' ] < 0 ) {
71- file_add [ 'permissions' ] [ 'create_time' ] = 0 ;
72- }
73- file_add [ 'modify_time' ] = Math . floor ( Math . trunc ( time_attr [ 'NSFileModificationDate' ] ?. timeIntervalSince1970 * 1000 || 0 ) ) ;
74- if ( file_add [ 'modify_time' ] < 0 ) {
75- file_add [ 'modify_time' ] = 0 ;
76- }
77- file_add [ 'access_time' ] = 0 ;
78- } else {
79-
81+ } else {
82+ file_add [ 'permissions' ] = { } ;
83+ }
84+ let exists = fileManager . fileExistsAtPathIsDirectory ( $ ( path + sub_files [ i ] ) , isDirectory ) ;
85+ if ( exists ) {
86+ file_add [ 'is_file' ] = ! isDirectory [ 0 ] ;
87+ }
88+ file_add [ 'size' ] = 0 ;
89+ if ( attr !== undefined ) {
90+ file_add [ 'size' ] = attr [ 'NSFileSize' ] ;
91+ let nsposix = attr [ 'NSFilePosixPermissions' ] ;
92+ // we need to fix this mess to actually be real permission bits that make sense
93+ file_add [ 'permissions' ] [ 'posix' ] = ( ( nsposix >> 6 ) & 0x7 ) . toString ( ) + ( ( nsposix >> 3 ) & 0x7 ) . toString ( ) + ( nsposix & 0x7 ) . toString ( ) ;
94+ file_add [ 'permissions' ] [ 'owner' ] = attr [ 'NSFileOwnerAccountName' ] + "(" + attr [ 'NSFileOwnerAccountID' ] + ")" ;
95+ file_add [ 'permissions' ] [ 'group' ] = attr [ 'NSFileGroupOwnerAccountName' ] + "(" + attr [ 'NSFileGroupOwnerAccountID' ] + ")" ;
96+ file_add [ 'permissions' ] [ 'hidden' ] = attr [ 'NSFileExtensionAttribute' ] === true ;
97+ file_add [ 'permissions' ] [ 'create_time' ] = Math . floor ( Math . trunc ( time_attr [ 'NSFileCreationDate' ] ?. timeIntervalSince1970 * 1000 || 0 ) ) ;
98+ if ( file_add [ 'permissions' ] [ 'create_time' ] < 0 ) {
99+ file_add [ 'permissions' ] [ 'create_time' ] = 0 ;
80100 }
81- files_data . push ( file_add ) ;
101+ file_add [ 'modify_time' ] = Math . floor ( Math . trunc ( time_attr [ 'NSFileModificationDate' ] ?. timeIntervalSince1970 * 1000 || 0 ) ) ;
102+ if ( file_add [ 'modify_time' ] < 0 ) {
103+ file_add [ 'modify_time' ] = 0 ;
104+ }
105+ file_add [ 'access_time' ] = 0 ;
106+ } else {
107+
82108 }
83- output [ 'files' ] = files_data ;
84- }
85- else {
86- output [ 'success' ] = false ;
109+ files_data . push ( file_add ) ;
87110 }
111+ output [ 'files' ] = files_data ;
112+ } else {
113+ output [ 'success' ] = false ;
88114 }
89- let nsposix = attributes [ 'NSFilePosixPermissions' ] ;
90- let components = ObjC . deepUnwrap ( fileManager . componentsToDisplayForPath ( path ) ) . slice ( 1 ) ;
91- if ( components . length > 0 && components [ 0 ] === "Macintosh HD" ) {
92- components . pop ( ) ;
93- }
94- // say components = "etc, krb5.keytab"
95- // check all components to see if they're symlinks
96- let parent_path = "/" ;
97- for ( let p = 0 ; p < components . length ; p ++ ) {
98- let resolvedSymLink = fileManager . destinationOfSymbolicLinkAtPathError ( $ ( parent_path + components [ p ] ) , $ . nil ) . js ;
99- if ( resolvedSymLink ) {
100- parent_path = parent_path + resolvedSymLink + "/" ;
101- } else {
102- parent_path = parent_path + components [ p ] + "/" ;
103- }
104- }
105- output [ 'name' ] = fileManager . displayNameAtPath ( parent_path ) . js ;
106- output [ 'parent_path' ] = parent_path . slice ( 0 , - ( output [ "name" ] . length + 1 ) ) ;
107-
108- if ( output [ 'name' ] === "Macintosh HD" ) { output [ 'name' ] = "/" ; }
109- if ( output [ 'name' ] === output [ 'parent_path' ] ) { output [ 'parent_path' ] = "" ; }
110- if ( command_params [ 'path' ] === "/dev" ) {
111- // /dev is apparently a special case for some reason and doesn't follow the normal fileManager.componentsToDisplayForPath
112- output [ "name" ] = "dev" ;
113- output [ "parent_path" ] = "/" ;
114- }
115- output [ 'size' ] = attributes [ 'NSFileSize' ] ;
116- output [ 'access_time' ] = 0 ;
117- output [ 'modify_time' ] = Math . floor ( Math . trunc ( time_attributes [ 'NSFileModificationDate' ] . timeIntervalSince1970 * 1000 ) ) ;
118- if ( output [ "modify_time" ] < 0 ) {
119- output [ "modify_time" ] = 0 ;
120- }
121- if ( attributes [ 'NSFileExtendedAttributes' ] !== undefined ) {
122- let extended = { } ;
123- let perms = attributes [ 'NSFileExtendedAttributes' ] . js ;
124- for ( let j in perms ) {
125- extended [ j ] = perms [ j ] . base64EncodedStringWithOptions ( 0 ) . js ;
126- }
127- output [ 'permissions' ] = extended ;
115+ }
116+ let nsposix = attributes ? attributes [ 'NSFilePosixPermissions' ] : "" ;
117+ let components = ObjC . deepUnwrap ( fileManager . componentsToDisplayForPath ( path ) ) . slice ( 1 ) ;
118+ if ( components . length > 0 && components [ 0 ] === "Macintosh HD" ) {
119+ components . pop ( ) ;
120+ }
121+ // say components = "etc, krb5.keytab"
122+ // check all components to see if they're symlinks
123+ let parent_path = "/" ;
124+ for ( let p = 0 ; p < components . length ; p ++ ) {
125+ let resolvedSymLink = fileManager . destinationOfSymbolicLinkAtPathError ( $ ( parent_path + components [ p ] ) , $ . nil ) . js ;
126+ if ( resolvedSymLink ) {
127+ parent_path = parent_path + resolvedSymLink + "/" ;
128128 } else {
129- output [ 'permissions' ] = { } ;
129+ parent_path = parent_path + components [ p ] + "/" ;
130130 }
131- output [ 'permissions' ] [ 'create_time' ] = Math . floor ( Math . trunc ( time_attributes [ 'NSFileCreationDate' ] . timeIntervalSince1970 * 1000 ) ) ;
132- if ( output [ 'permissions' ] [ 'create_time' ] < 0 ) {
133- output [ 'permissions' ] [ 'create_time' ] = 0 ;
131+ }
132+ output [ 'name' ] = fileManager . displayNameAtPath ( parent_path ) . js ;
133+ output [ 'parent_path' ] = parent_path . slice ( 0 , - ( output [ "name" ] . length + 1 ) ) ;
134+ if ( output [ 'name' ] === "Macintosh HD" ) { output [ 'name' ] = "/" ; }
135+ if ( output [ 'name' ] === output [ 'parent_path' ] ) { output [ 'parent_path' ] = "" ; }
136+ if ( command_params [ 'path' ] === "/dev" ) {
137+ // /dev is apparently a special case for some reason and doesn't follow the normal fileManager.componentsToDisplayForPath
138+ output [ "name" ] = "dev" ;
139+ output [ "parent_path" ] = "/" ;
140+ }
141+ output [ 'size' ] = attributes ? attributes [ 'NSFileSize' ] : 0 ;
142+ output [ 'access_time' ] = 0 ;
143+ output [ 'modify_time' ] = time_attributes ? Math . floor ( Math . trunc ( time_attributes [ 'NSFileModificationDate' ] . timeIntervalSince1970 * 1000 ) ) : 0 ;
144+ if ( output [ "modify_time" ] < 0 ) {
145+ output [ "modify_time" ] = 0 ;
146+ }
147+ if ( attributes && attributes [ 'NSFileExtendedAttributes' ] !== undefined ) {
148+ let extended = { } ;
149+ let perms = attributes [ 'NSFileExtendedAttributes' ] . js ;
150+ for ( let j in perms ) {
151+ extended [ j ] = perms [ j ] . base64EncodedStringWithOptions ( 0 ) . js ;
134152 }
135- output [ 'permissions' ] [ 'posix' ] = ( ( nsposix >> 6 ) & 0x7 ) . toString ( ) + ( ( nsposix >> 3 ) & 0x7 ) . toString ( ) + ( nsposix & 0x7 ) . toString ( ) ;
153+ output [ 'permissions' ] = extended ;
154+ } else {
155+ output [ 'permissions' ] = { } ;
156+ }
157+ output [ 'permissions' ] [ 'create_time' ] = time_attributes ? Math . floor ( Math . trunc ( time_attributes [ 'NSFileCreationDate' ] . timeIntervalSince1970 * 1000 ) ) : 0 ;
158+ if ( output [ 'permissions' ] [ 'create_time' ] < 0 ) {
159+ output [ 'permissions' ] [ 'create_time' ] = 0 ;
160+ }
161+ if ( includeAttributes ) {
162+ output [ 'permissions' ] [ 'posix' ] = ( ( nsposix >> 6 ) & 0x7 ) . toString ( ) + ( ( nsposix >> 3 ) & 0x7 ) . toString ( ) + ( nsposix & 0x7 ) . toString ( ) ;
136163 output [ 'permissions' ] [ 'owner' ] = attributes [ 'NSFileOwnerAccountName' ] + "(" + attributes [ 'NSFileOwnerAccountID' ] + ")" ;
137164 output [ 'permissions' ] [ 'group' ] = attributes [ 'NSFileGroupOwnerAccountName' ] + "(" + attributes [ 'NSFileGroupOwnerAccountID' ] + ")" ;
138165 output [ 'permissions' ] [ 'hidden' ] = attributes [ 'NSFileExtensionHidden' ] === true ;
139- if ( command_params [ 'file_browser' ] ) {
140- return { "file_browser" : output , "completed" : true , "user_output" : "added data to file browser" } ;
141- } else {
142- return { "file_browser" : output , "completed" : true , "user_output" : JSON . stringify ( output , null , 6 ) } ;
143- }
144166 }
145- else {
146- return {
147- "user_output" : "Failed to get attributes of file. File doesn't exist or you don't have permission to read it" ,
148- "completed" : true ,
149- "status" : "error"
150- } ;
167+ if ( command_params [ 'file_browser' ] ) {
168+ return { "file_browser" : output , "completed" : true , "user_output" : "added data to file browser" } ;
169+ } else {
170+ return { "file_browser" : output , "completed" : true , "user_output" : JSON . stringify ( output , null , 6 ) } ;
151171 }
152-
153172 } catch ( error ) {
154173 return {
155174 "user_output" : "Error: " + error . toString ( ) ,
0 commit comments