Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Percent encoding: here's a test case with a couple failures #32

Closed
DressTheMonkey opened this issue Mar 8, 2014 · 4 comments
Closed

Comments

@DressTheMonkey
Copy link

I'm having problems with quoting slash (/) and plus (+). I looked at the code a bit; the problem seems to be pathComponents doing some unquoting. I think this is why Apple have now introduced NSURLComponents, but that doesn't help if you want to be compatible with older versions. Here's a test case you can drop into your test .m file to demonstrate:

- (void)testPercentEncoding {
    /*
     from http://en.wikipedia.org/wiki/Percent-encoding
     !   #   $   &   '   (   )   *   +   ,   /   :   ;   =   ?   @   [   ]
     %21 %23    %24 %26 %27 %28 %29 %2A %2B %2C %2F %3A %3B %3D %3F %40 %5B %5D
     */

    [self route:@"tests://user/view/joel%21levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel!levin"});

    [self route:@"tests://user/view/joel%23levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel#levin"});

    [self route:@"tests://user/view/joel%24levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel$levin"});

    [self route:@"tests://user/view/joel%26levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel&levin"});

    [self route:@"tests://user/view/joel%27levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel'levin"});

    [self route:@"tests://user/view/joel%28levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel(levin"});

    [self route:@"tests://user/view/joel%29levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel)levin"});

    [self route:@"tests://user/view/joel%2Alevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel*levin"});

    /*
     Fails: tries to match 'joel levin' with 'joel+levin'
     */
    [self route:@"tests://user/view/joel%2Blevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel+levin"});

    [self route:@"tests://user/view/joel%2Clevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel,levin"});

    /*
     Fails: tries to match (null) with 'joel/levin'
     */
    [self route:@"tests://user/view/joel%2Flevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel/levin"});

    [self route:@"tests://user/view/joel%3Alevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel:levin"});

    [self route:@"tests://user/view/joel%3Blevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel;levin"});

    [self route:@"tests://user/view/joel%3Dlevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel=levin"});

    [self route:@"tests://user/view/joel%3Flevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel?levin"});

    [self route:@"tests://user/view/joel%40levin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel@levin"});

    [self route:@"tests://user/view/joel%5Blevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel[levin"});

    [self route:@"tests://user/view/joel%5Dlevin"];
    JLValidateAnyRouteMatched();
    JLValidateParameterCount(1);
    JLValidateParameter(@{@"userID": @"joel]levin"});

}

joeldev added a commit that referenced this issue Mar 9, 2014
@joeldev
Copy link
Owner

joeldev commented Mar 9, 2014

Thanks for this as well. A few things:

  1. %2F (/) will not be supported at this time due to the NSURL pathComponents issue you mention.
  2. %2B (+) is now supported by calling [JLRoutes setShouldDecodePlusSymbols:NO];

The reason 2 has been solved with a setting is that I don't believe most people actually want to get the raw + in the resulting variable. For those that do, they can ask JLRoutes not to decode plus symbols and the value will come through as expected.

@joeldev joeldev closed this as completed Mar 9, 2014
@isaaclimdc
Copy link

What if I needed %2F to be supported? What should I do?

@EkkoG
Copy link

EkkoG commented Aug 6, 2017

From w3c ASCII Encoding Reference, the plus(+) encode to %2B, space encode to 20%, as setShouldDecodePlusSymbols: default option, NSURLComponents decode %2B to +, setShouldDecodePlusSymbols: replace the + symbols to space, it more like a bug, %2B shoult never decode to space.

@EkkoG
Copy link

EkkoG commented Aug 6, 2017

For sometimes, space encode to +, as Wikipedia says, https://www.wikiwand.com/en/Percent-encoding#The_.60application.2Fx-www-form-urlencoded.60_type

for these cases, it needs an option to replace the plus to space, but it should work in the beginning, e.g. before [[NSURLComponents alloc] initWithString:@"http://example.com/issue?p=a"], and this change will avoid replacing the %2B to space, because %2B raw value is +, after decode, it should also be +,not space.

Also, from RFC 3986, + is a remaining character, for most cases space will be encoded to %20, not plus, so I think setShouldDecodePlusSymbols: default value should be NO, not YES.

Thanks.

@joeldev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants