SSBs not working when app is Sandboxed

  1. 8 weeks ago

    Beatrix W

    Feb 12 Pre-Release Testers, Third Party Store Europe (Germany)

    In the AppStore version of my app the SSBs aren't working anymore. Saving is okay. But when the app is Sandboxed then the result of getting the folderitem back always is Nil. I had a look with Christian at the code, but he also didn't have an idea.

    Private Function getPrefFolderitemLite(fieldName as string) as Folderitem
      
      'get data from preferences
      if fieldName = "" then Return Nil
      if not CheckForPrefs then Return Nil
      if not theCFPrefs.AppSynchronize(theCFPrefs.kCFPreferencesCurrentApplication) Then 
        globals.theErrorLog.DialogErrorProceed(kErrorSynchronize)
      end if
      Dim theCFObject As CFObjectMBS = theCFPrefs.CopyAppValue(NewCFStringMBS(fieldName), theCFPrefs.kCFPreferencesCurrentApplication)
      if theCFObject = Nil then Return nil
      
      'get base64 encoded path
      dim theData as String = DecodeBase64(CFStringMBS(theCFObject).str)
      if theData = "" then Return Nil
    
        dim theFolderitem as new FolderItem(theData, FolderItem.PathModes.Native)
        Return theFolderitem
        
    End Function
    Private Sub setPrefFolderitemLite(fieldName as string, fieldValue as Folderitem)
      
      'set a folderitem preference value
      
      if fieldName = "" then Return
      
      'just encode the path in base64
      dim theData as String
      if fieldValue <> Nil then theData = EncodeBase64(fieldValue.NativePath)
      
      'make CFObjectMBS
      dim theCFObject As CFObjectMBS = NewCFStringMBS(theData)
      
      'save to prefs
      if not CheckForPrefs then Return
      theCFPrefs.SetAppValue(NewCFStringMBS(FieldName), theCFObject, theCFPrefs.kCFPreferencesCurrentApplication)
      if not theCFPrefs.AppSynchronize(theCFPrefs.kCFPreferencesCurrentApplication) Then
        globals.theErrorLog.DialogErrorProceed(kErrorSynchronize)
      end if
        
    End Sub

    Does anyone have an idea what might cause the problem? I'm really out of ideas. For now I have made a workaround with a global because the folderitem doesn't absolutely need to be saved. But it's really not a good idea with the global.

    Xojo 2019r3, MBS latest version. Different versions of macOS.

  2. @Beatrix W — I am not sure that creating a FolderItem from an absolute path works with sandboxing, because your app does (usually) not have access to each individual folder in the path. I think you would better store an Alias record or, even better, a Bookmark.

    Here are 2 standalone methods to get Bookmark data from a FolderItem and resolve Bookmark data into a FolderItem, in case you need them.

    Hope that helps

    Public Function GetBookmarkData(extends f as FolderItem, relativeTo as FolderItem = nil, Mode as Integer = 0) as String
      //# Mimicks (better) FolderItem.GetSaveInfo with modern system calls. Mode is actually not used. The bookmark will be relative if and only if you set a RelativeTo FolderItem.
      
      declare function NSClassFromString Lib CocoaLib ( aClassName as CFStringRef ) As Ptr
      declare function URLWithString lib CocoaLib selector "URLWithString:" ( cls as Ptr, URLString as CFStringRef ) as Ptr
      declare function BookmarkDataWithOptions lib CocoaLib selector "bookmarkDataWithOptions:includingResourceValuesForKeys:relativeToURL:error:" (id as Ptr, options as Integer, rsrc as Ptr, relativeTo as Ptr, byref error as Ptr) as Ptr
      declare function DataLength lib CocoaLib  selector "length" (id as Ptr) as integer
      declare sub DataBytes lib CocoaLib selector "getBytes:length:" (id as Ptr, dest as Ptr, length as integer)
      
      const CocoaLib = "Cocoa.framework"
      
      dim url as Ptr = URLWithString( NSClassFromString( "NSURL" ), f.URLPath )
      dim relativeNSURL as Ptr
      dim err as Ptr
      
      if relativeTo<>nil then
        relativeNSURL = URLWithString( NSClassFromString( "NSURL" ), relativeTo.URLPath )
      end if
      
      dim data as Ptr = BookmarkDataWithOptions( url, 0, nil, relativeNSURL, err )
      
      if data<>nil then
        dim L as integer = DataLength( data )
        dim mb as new MemoryBlock( L )
        DataBytes  data, mb, L
        return  mb.StringValue( 0, L )
      end if
      
    End Function
    Public Function ResolveBookmark(data as String, relativeTo as FolderItem = nil) as FolderItem
      //# Resolves a bookmark and returns the corresponding FolderItem. If you created a relative Bookmark, you MUST provide the same RelativeTo parameter as during creation.
      
      declare function NSClassFromString Lib CocoaLib ( aClassName as CFStringRef ) As Ptr
      declare function URLWithString lib CocoaLib selector "URLWithString:" ( cls as Ptr, URLString as CFStringRef ) as Ptr
      declare function URLByResolvingBookmarkData lib CocoaLib selector "URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:" (cls as Ptr, data as Ptr, options as integer, relativeto as Ptr, byref stale as Boolean, byref err as Ptr) as Ptr
      declare function DataWithBytes lib CocoaLib selector "dataWithBytes:length:" (cls as Ptr, bytes as Ptr, length as integer) as Ptr
      declare function absoluteString lib CocoaLib selector "absoluteString" (id as Ptr) as CFStringRef
      
      dim url as Ptr
      dim relativeNSURL as Ptr
      dim stale as boolean
      dim err as Ptr
      
      if relativeTo<>nil then
        relativeNSURL = URLWithString( NSClassFromString( "NSURL" ), relativeTo.URLPath )
      end if
      
      dim mb as MemoryBlock = data
      dim nsdata as Ptr  = DataWithBytes( NSClassFromString( "NSData" ), mb, mb.size )
      
      url = URLByResolvingBookmarkData( NSClassFromString( "NSURL" ), nsdata, 0, relativeNSURL, stale, err )
      
      if url<>nil then
        return  new FolderItem( absoluteString( url ), FolderItem.PathTypeURL )
      end if
      
    End Function
  3. Beatrix W

    Feb 12 Pre-Release Testers, Third Party Store Europe (Germany)

    Thanks, I'll try your code.

  4. Sam R

    Feb 12 Pre-Release Testers, Xojo Pro, Third Party Store Hengchun, Pingtung, Taiwan

    That doesn't look like a Security Scoped Bodgemark, it looks like you're just encoding and decoding the path to the file.

  5. Beatrix W

    Feb 12 Pre-Release Testers, Third Party Store Europe (Germany)

    Ha, I'm going senile. You are quite correct. Where did my code go?

or Sign Up to reply!