Jump to content

Allen@Grijjy

Members
  • Content Count

    42
  • Joined

  • Last visited

  • Days Won

    5

Posts posted by Allen@Grijjy


  1. 1 hour ago, Dave Nottage said:

    The problem is that PAServer signs the extension with the wrong entitlements, and in Chris' (and my) case, it's unnecessary because the extension has already been correctly signed, i.e. it does not even need to be touched. Replacing the extension in the .app bundle, and using iosinstall to install the it solves the problem, at least debugging-wise. I expect a similar process will be needed for repackaging the .ipa.

     

    Thanks, I have been racking by brain about this.  I wrote an article on how to do it back in 2018 for Grijjy but couldn't get any of it to work with Delphi 12 again.  I tried just about everything so I appreciate the insight!


  2. 4 hours ago, Anders Melander said:

    Yes. This is the exact default setup that I use.

     

    If I use that command line, I always get '0' source lines.  Here is the output for the following:

    -v -pause -bind:C:\Users\Allen\Desktop\Test1.exe C:\Users\Allen\Desktop\Test1.map -include:0001

    ---->

    map2pdb - Copyright (c) 2021 Anders Melander
    Version 3.0.1
    
    Constructed a new PDB GUID: {33C40D0A-BC13-43D4-A6E3-D7D23966F480}
    Output filename not specified. Defaulting to Test1.pdb
    Reading MAP file
    - Segments
    - Modules
    - Symbols
    Warning: [36728] Failed to resolve symbol to module: [0004:0000000000008260] SysInit.TlsLast
    Warning: [36731] Failed to resolve symbol to module: [0003:00000000FF887000] SysInit.__ImageBase
    - Line numbers
    Include filter eliminated 1,114 module(s), 60,204 symbol(s)
    Collected 0 modules, 0 symbols, 0 lines, 280 source files
    Constructing PDB file
    - Collecting source file names
    - Module streams
    - Strings stream
    - PDB Info stream
    - TPI stream
    - Symbols stream
    - DBI stream
    - IPI stream
    - Finalizing PDB file
    - 15 blocks written in 1 intervals
    Patching PE file
    - PE32+ image (64-bit)
    - PDB file name has been stored in debug data.
    - PE file has been updated.
    Elapsed time: 00:00:00.246

     

    If I take the exact same map file and do the following instead, Here is the output:

    -v -pause -bind:C:\Users\Allen\Desktop\Test1.exe C:\Users\Allen\Desktop\Test1.map

    ---->

    map2pdb - Copyright (c) 2021 Anders Melander
    Version 3.0.1
    
    Constructed a new PDB GUID: {44F58444-CC5E-4CA2-B03E-288B255CC688}
    Output filename not specified. Defaulting to Test1.pdb
    Reading MAP file
    - Segments
    - Modules
    - Symbols
    Warning: [36728] Failed to resolve symbol to module: [0004:0000000000008260] SysInit.TlsLast
    Warning: [36731] Failed to resolve symbol to module: [0003:00000000FF887000] SysInit.__ImageBase
    - Line numbers
    Collected 1,114 modules, 60,204 symbols, 155,944 lines, 280 source files
    Constructing PDB file
    - Collecting source file names
    - Module streams
    - Strings stream
    - PDB Info stream
    - TPI stream
    - Symbols stream
    - DBI stream
    - IPI stream
    - Finalizing PDB file
    ERangeError: Range check error
    Elapsed time: 00:00:03.714
    Done - Press enter to continue

    Notice (2) things.  First I get all the sources lines, but before I did not.  Also I get a Range Check Error (at the bottom).  I am really using the syntax correctly?  I guess I don't understand the benefit of generating a PDB without line information?

     

     

    4 hours ago, Anders Melander said:

    So far I don't have enough test cases of map files with these overlapping segments to be able to make a decision on how best to handle them, so if I could get my hand on the one you have that would be great.

    Also, if you could examine the corresponding exe file (I recommend using PE Tools) to find out what the actual segment offsets and sizes are (because they're obviously not what the map file states) that would be a big help.

     

    I am willing to send the .map file I am using for you to examine if there is a private means of doing so.  I don't want to share it publicly.  I grabbed to PE information for it.  It does seem quite different from Delphi's output:

     Start                 Length     Name                   Class
     0001:0000000000401000 006CD7B8H .text                   CODE
     0002:0000000000ACF000 000A9208H .data                   DATA
     0003:0000000000B79000 00011F20H .bss                    BSS
     0004:0000000000400000 00008260H .tls                    TLS
     0005:0000000000BDE000 0004FF5CH .pdata                  PDATA

     

    1412252392_Test1-PESections.thumb.PNG.4101e02508f4a77543e6eed5859acf90.PNG

     

    4 hours ago, Anders Melander said:

    The best would of course be if Embarcadero fixed the map file but I'm not holding my breath for that, and I still need to be able to handle what's already out there.

    I totally agree.  If you have a QC report with Embarcadero I would be happy to vote for it and escalate it.

     

    I really would like to see if we could get to the bottom of these things because it's an important capability and I would live to share it with the wider audience.  Happy to help in any way on this.


  3. 20 hours ago, Anders Melander said:

    -include and -exclude are filters that are applied after the map file has been parsed.

    • If neither is specified, everything is included.
    • If -include is specified, everything that doesn't satisfy the include filter is ignored.
    • If -exclude is specified, everything that does satisfies the exclude filter is ignored.

    This is where I am confused (and I have read all the existing documentation).  You recommend configuring a tool in Delphi with these parameters:

    -debug -v -pause -bind:$EXENAME $PATH($EXENAME)$NAMEONLY($EXENAME).map -include:0001

     

    When I do this, it will parse my map file correctly, but it won't load any source lines regardless of the segments that I include.  If I I change to something like this:

    -v -pause -bind:$EXENAME $PATH($EXENAME)$NAMEONLY($EXENAME).map -include:0001;0003;0004

    It also doesn't load any source lines.  

     

    I checked this within the debugger directly.  It enumerates the files correctly, it just doesn't consume them into the FSourceLines collection.   

     

    Is my syntax correct or am I supposed to be doing this:

    -debug -v -pause -bind:$EXENAME $PATH($EXENAME)$NAMEONLY($EXENAME).map -include:0001;0002;*

    so I am indicating both filenames and segments to include?

    20 hours ago, Anders Melander said:

    Well, overlapping segments should never occur so that would be a bug in Delphi if you have that in the map file.

    In the first version of your your other message, you stated that you encountered some exceptions but were able to work around them by modifying the source. I'll of course be interested to know exactly what the problem was and what you changed, so I can get it merged into the source if there really is a problem.

    I'll probably also need to see the map files to get to the bottom of this. You can either create a (public) issue at Bitbucket or PM them to me here.

     

    I would be happy to assist in any way I can.  I think it's a great tool and would love to do an Embarcadero Coderage MVP session on how to use some of the industry standard profilers with your utility in the future, if that's okay.

     

    I noticed other people have encountered the same issue with consuming overlapping segments.   In my case I modified the code to skip the overlapping segments instead of raising an exception and stopping.  For example, Delphi emitted the map file segments as:

     

     Start                 Length     Name                   Class
     0001:0000000000401000 006CD7B8H .text                   CODE
     0002:0000000000ACF000 000A9208H .data                   DATA
     0003:0000000000B79000 00011F20H .bss                    BSS
     0004:0000000000400000 00008260H .tls                    TLS
     0005:0000000000BDE000 0004FF5CH .pdata                  PDATA

     

    TDebugInfoSegment.CheckOverlap subsequently raised an exception:

    Project map2pdb.exe raised exception class Exception with message 'Overlapping segments: .tls [0004:0000000000400000] and .text [0001:0000000000401000]'.


  4. 1 hour ago, chkaufmann said:

    Thanks for your instructions. I did like this, but when I call map2pdb I get a long list of errors. For example I get many lines like "Debug: Module has no source files: xxxxxxx" where xxxxxxx is the name of a unit

    Guess we are both working on this at the same time!  I had the same issue yesterday, but I figured out that -include:0001 (or whatever code segments you are analyzing) doesn't actually load the source lines.  I haven't debugged it fully yet, but if I switch to -include:* (using a filename wildcard instead) it works.   The main thing is to make sure that the -debug output says it loaded more than 0 lines.

    Also, it has some issue with overlapping segments from the map files, so I had to make a source code change to work around it, but that issue may be project specific.


  5. I am little late to this party, but stumbled across this wonderful utility, so thank you for it!  At first map2pdb didn't consume my map files without throwing some exceptions, but I made a few code changes and it works wonderfully now.  I was able to use it with Intel VTune which is really nice!  The issues I encountered was that it complained about 'overlapping segments' between .tls and the .data segments.  It also wouldn't load source lines if I use -include:0001 or -include:0001;0002;etc..

     

    I was able to modify the sources to exclude the .tls segment and if I changed to -include:* using a wildcard then it properly loaded all the source lines from the various segments.  Anyway, thanks for this!


  6. Seems to be caused by remnants in the project .dsk files.  If you edit them or purge them, the problem appears to go away.  Do a search for "Documentation.htm" in your *.dsk files.


  7. Sorry, missed your original post on this.  I don't mind your efforts here.  OpenSsl is particularly tricky because quite often it is installed with the operating system and if you use dynamic library version the imports will get confused about which library you are using, since there are 2 of them that cross-reference each other.  To avoid this, I try to build the static versions which are linked directly into the project using the "dependency" keyword.  Also, the Mac was particularly a pain because symbolic linking will force the dynamic library to find OpenSsl elsewhere so I merged both libraries into one to avoid that.  But yes, placing all the libraries into a single path with the header unit avoids a lot of frustration for static libraries.


  8. Did some more reading here.  Apple specifically says that extensions are not allowed to launch their host application unless it's a Today widget,

    "A Today widget (and no other app extension type) can ask the system to open its containing app by calling the openURL:completionHandler: method of the NSExtensionContext class. "

    https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html#//apple_ref/doc/uid/TP40014214-CH2-SW2

     

    You may get rejected by Apple from the App Store for violating guidelines.  That being said, I suspect from reading on StackOverflow that is exactly what some Share extensions are doing and they are in the App store.

     

    I attached an example ShareViewController.m that *may* work.  Of course you will need to modify the urlString and replace https:// with abcd:// to launch the Url Protocol handler.

     

    ShareViewController.m

    • Like 2

  9. Additionally, from what I have read, you cannot open/run the containing application (in your case a Delphi host application) from the share extension if the app is not already running.  However, you can start your application by running a Url Protocol handler to launch your Delphi app.  I was planning on writing a blog article about this topic.

     

    I put together a small example of how to implement a protocol handler that works on macOS and iOS and Delphi apps.  It is attached here.  There is a small EventManager unit included to simplify the process.  The only thing you really need to do is modify the info.plist.TemplateOSX.xml (or info.plist.TemplateiOS.xml) and specify your Url Protocol handler method. 

     

    For this example I use "abcd".  So if you run this example application and then open Safari and type a Url like, abcd://www.google.com then you will receive that message in your Delphi app.  It will automatically run your Delphi app if it is not already running.

     

    You should modify your didSelectPost so that it takes the urlString and changes the HTTP/S method to use your Url Protocol Handler method and then executes OpenUrl() to open the Url Protocol Handler thereby sending the Url to your Delphi app even if your app is not running.

     

    - (void)didSelectPost {
        NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
        NSItemProvider *itemProvider = item.attachments.firstObject;
        if ([itemProvider hasItemConformingToTypeIdentifier:@"public.url"]) {
            [itemProvider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(NSURL *url, NSError *error) {
                NSString *urlString = url.absoluteString;

                // Call your Delphi app here!!!

     

            }];
        }
    }

     

     

    ProtocolHandler.zip


  10. I went back a re-read your original post.  Thanks for the clarification..  I think you need to place everything inside of "didSelectPost".  Warning!  I have not tested this example:

     

    - (void)didSelectPost {
        NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
        NSItemProvider *itemProvider = item.attachments.firstObject;
        if ([itemProvider hasItemConformingToTypeIdentifier:@"public.url"]) {
            [itemProvider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(NSURL *url, NSError *error) {
                NSString *urlString = url.absoluteString;

                // Call your Delphi app here!!!

                // Share access to an NSUserDefaults object
                NSUserDefaults *sharedSettings = [[NSUserDefaults alloc] initWithSuiteName: AppGroupName];

                // Set shared object key/value
                [[NSUserDefaults sharedSettings] setObject:urlString forKey:@"TheUrlString"];

                // Synchronize
                [sharedSettings synchronize];
            }];
        }
    }

     

    Replace TheUrlString with the key you are using for GetObject on the Delphi app side.

     

    Also you could skip the constant for AppGroupName and instead write the line like:

    NSUserDefaults *sharedSettings = [[NSUserDefaults alloc] initWithSuiteName: @"group.it.diesys.yadiesys"];

     


  11. I sent you an email with some example attachments separately.... In regards to your questions:

     

    My app must listen to receive links (both closed and open) and it is not necessary to send anything to the extension.

    Does this mean your app must open/run if it’s not running when the extension needs it?

     

    To do this I have to enter this code but it is not clear where. In the OnCreate of the main form?

    You can do it anywhere in code. 

     

    I think this part is used to send data to the Share Extension and therefore in my case it should not be necessary, right?

    Yes, if you only want to receive from the share extension it is not required.  From your description of your requirements you need to translate the example from Delphi into Objective C and put that into your plugin in XCode.

     

    Should the synchronize be called every time something is sent?

    Yes

     

    How does the app know when a link is sent to it? and how can I extract it?

    The app should poll using something like a TTimer.  It needs to call synchronize to make sure it has an updated copy of the data during the polling.

     

    Where should I insert this code? NSString *const AppGroupName = @" group.it.diesys.yadiesys'";

    The constant is at the top of your plugin code directly after @implementation.

     

    This shouldn't be necessary because my Extension just has to send, right?

    Correct.  You need to do something like we show in Delphi, but in Objective-C inside of XCode in your plugin.  That should look something like this:

     

    // Create and share access to an NSUserDefaults object

    NSUserDefaults *sharedSettings = [[NSUserDefaults alloc] initWithSuiteName: AppGroupName];

       

    // Set shared object key/value

    [[NSUserDefaults sharedSettings] setObject:somevalue forKey:@"somekey"];

     

    // Synchronize

    [sharedSettings synchronize];

     

    Where should I insert this code? Now what I have to do is send the Link, how do I capture and send it?

    I have never made this type of app extension, so I am not sure where you place the code on XCode side until I know what extension you are making.  Each app extension works differently.

     

    Are you making a “share” extension for Safari?  Are you trying to capture all urls from Safari into your app?  Could you explain what you are doing a little bit better?  If you could clarify I might be able to advise you where to capture what you want to capture.

     

    I have never made this type of extension so I don’t know if what you want to do is possible.  Apple has all sorts of weird rules and restrictions on grabbing data from other apps.


  12. 11 hours ago, Massimiliano S said:

    Hi dave,
    sorry it's always me and I would love to repay you for your precious help
    I was able to compile the plug in and make IOS see my app in the share.
    Now unfortunately I have to complete the code but I have problems doing it and the example is not very clear to me
    https://blog.grijjy.com/2018/11/15/ios-and-macos-app-extensions-with-delphi/

    What I need to do is put the code in xcode to send the link in my plugin
    and put the code in delphi in my app to get the code.

    Hello Massimillano,

     

    I sent you an email this morning but it said you were "out of the office".  The article shows how to use XPC to exchange the information with your extension.  All the code required to do that is included in the blog article, it's not much.

     

    The strange part is you have to create an "Application group" in the Apple developer portal and then add it to your info.plist in order to use XPC (inter-process communication between the app and the extension)

     

    Let me know if you have any questions


  13. Latest article on how to use the latest version of OpenSsl 1.1.1 with Delphi directly to create X.509 certificates, decode, verify, encode and sign JSON Web Tokens and generate random data. Additionally we will do this in a way that works on Delphi supported platforms including Windows, macOS, iOS, Android and Linux as well as all current compiler targets for 32 and 64-bit devices.

     

    https://blog.grijjy.com/2020/08/04/using-openssl-1-1-1-with-all-delphi-target-platforms/

     

    OpenSsl.thumb.png.9f0fddca0413a86f01fab884eff0f74c.png 

    • Like 2

  14. I am very happy that FastMM5 is now available and also with the new licensing scheme.  We plan to use it in our heavily threaded 64-bit http/socket servers.  While I wouldn't have used it at all if it was GPL only, having a commercial offering at a reasonable price is actually more preferable because I like the idea of a properly maintained memory manager for our commercial products.  There are plenty of free memory managers around for Delphi, that are barely maintained.

    • Like 7

  15. I tried it both inside the debugger and outside the debugger with 10.3 with Win32 on Windows 7.  At first it didn't work at all, as you described.  Then it suddenly started working after I tried solution #1 in this article, https://knowledge.autodesk.com/search-result/caas/sfdcarticles/sfdcarticles/Install-Failure-Error-997-Overlapped-I-O-operation-is-in-progress.html

     

    Now I am not so sure why it started working and I cannot stop it from working, go figure.

     

    Since I know you are skeptic of actually running and testing on Win7, I attached a screenshot.

    shot1.png

    • Like 1

  16. 4 hours ago, ZRomik said:

    HTTP Error 400. The request has an invalid header name.

    I think an incorrectly spelled name like autorization would qualify as an invalid header name.  Also, just because you have an access token or refresh token, doesn't mean you made a request using an authorization header yet, as those required for bearer tokens.  It is very common to use query parameters as part of a URI path to obtain the access and refresh token on OAuth implementations.

×