Make an NSURL with an encoded plus (%2B) - iphone

I need to pass a timestamp with a timezone offset in a GET request, e.g.,
2009-05-04T11:22:00+01:00
This looks like a two arguments "2009-05-04T11:22:00" and "01:00" to the receiving PHP script (over which I've no control).
NSURL doesn't encode plus signs, but if I make an NSURL using the string
2009-05-04T11:22:00%2B01:00
the url I end up with contains:
2009-05-04T11:22:00%252B01:00
Any ideas how I can preserve my encoded plus sign or just plain prevent NSURL from encoding anything?

What worked for me was doing the UTF8 conversion, then replacing the + sign with %2B:
NSString *urlString =
[NSString stringWithFormat:#"%#/iphone/push/create?pn[token]=%#&pn[send_at]=%#",
kHTTPURL, appDelegate.deviceAPNToken, [dateTimeToUse description]];
urlString =
[[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];

The string should be URL encoded.
Here is a category for NSString that will help:
NSString+Additions.h
#interface NSString (Additions)
- (NSString *)stringByURLEncoding;
NSString+Additions.m
#import "NSString+Additions.h"
#implementation NSString (Additions)
- (NSString *)stringByURLEncoding {
return (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
}

Use NSString's stringByAddingPercentEscapesUsingEncoding: method on the text you want to include as an argument.
As its name implies, the method will convert return an auto-released string containing an url-safe version of the receiver.

Thought I may as well provide my workaround as an answer, as I don't think there's a good solution to the original problem.
The plus sign (+) is completely valid in a URL, so my solution was to convert the time to GMT and remove the timezone/DST offset from the string. I'll leave it as an exercise for the reader to determine the value of secondsFromGMT below as, in my case, it's always the same because I'm only interested in timestamps generated by a web server.
NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil
timeZone:[NSTimeZone
timeZoneForSecondsFromGMT:secondsFromGMT
] locale:nil] stringByReplacingOccurrencesOfString:#" +0000" withString:#""];

Solution when using URLComponents (Swift 3):
var params = ["email": "user+ios-default#example.com", "name": "John Brown"]
var components = URLComponents(string: "http://www.example.com")!
components.path = "/login"
components.queryItems = params.map { URLQueryItem(name: $0, value: $1) }
let url_NoFix = components.url!
// http://www.example.com/login?name=John%20Brown&email=user+ios-default#example.com
let cs = CharacterSet(charactersIn: "+").inverted
let q = components.percentEncodedQuery?.addingPercentEncoding(withAllowedCharacters: cs)
components.percentEncodedQuery = q
let url_Fixed = components.url!
// http://www.example.com/login?name=John%20Brown&email=user%2Bios-default#example.com

encode you string by using below code
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,NULL,(CFStringRef)#"+",kCFStringEncodingUTF8);
this will encode + of you string which will prevent replacement of + by %2b while posting data in post method

To get encoded plus (%2B) (It works with all charcters) use CFURLCreateStringByAddingPercentEscapes as
/**
get parameterized url from url and query parameters.
*/
+(NSString *)getParameterizedUrl:(NSString *)url withParameters:(NSDictionary *)queryDictionary
{
NSMutableArray *mutablePairs = [NSMutableArray array];
for (NSString *key in queryDictionary) {
[mutablePairs addObject:[NSString stringWithFormat:#"%#=%#", CTPercentEscapedQueryStringKeyFromStringWithEncoding(key, NSUTF8StringEncoding), CTPercentEscapedQueryStringValueFromStringWithEncoding(queryDictionary[key], NSUTF8StringEncoding)]];
}
return [[NSString alloc]initWithFormat:#"%#?%#",url,[mutablePairs componentsJoinedByString:#"&"]];
}
static NSString * const kCharactersToBeEscapedInQueryString = #":/?&=;+!##$()',*";
static NSString * CTPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
static NSString * const kCharactersToLeaveUnescapedInQueryStringPairKey = #"[].";
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}
static NSString * CTPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}
And use in your code as
NSMutableDictionary *params = [[NSMutableDictionary alloc]init];
[params setObject:#"2009-05-04T11:22:00+01:00" forKey:#"timestamp"];
NSString *urlString = [self getParameterizedUrl:#"http://www.example.com" withParameters:params];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

Related

url Encoding in ios

I get a link from server to image has already been Encoding so it comes with %20
But sometimes I get a code include Hebrew characters, so I need to do Encoding agian , With the above code:
But after my Encoding i get in response that % 20 change to % 2520
static CFStringRef charsToEscape = CFSTR("&=");
+ (NSString *)escapeStringByAddingPercentEscapes: (NSString*) string {
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)string,
NULL,
charsToEscape,
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease];
}
i tried to add % to charsToEscape like this:
static CFStringRef charsToEscape = CFSTR("&=%");
but it did not help.
thanks
NSString *urlString = #"----YOUR URL HERE----";
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
Your idea is good if I did not get the Hebrew characters in the link.
But I found the solution , I just sent the % in the parameter legalURLCharactersToBeEscaped
now i use in the function like this:
static CFStringRef charsToEscape = CFSTR("&=");
static CFStringRef charsUnchanged = CFSTR("%");
+ (NSString *)escapeStringByAddingPercentEscapes: (NSString*) string {
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)string,
charsUnchanged,
charsToEscape,
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease];
}
thanks

Add text/data along with special characters as a parameter to api(url) in iphone

I am new to Obj-c. I am adding parameter like text (the text may have special characters also)to url. But the url is showing nil, it's not taking value from string.
For example:
NSString*strUrl=[NSString stringWithFormat:#"hi how#!#$%^^&*()_=+ r u <>,./ where r u"];
NSString *strMainUrl=[NSString stringWithFormat:#"http://google.com/API/index.php action=listIt&data=%#",strUrl];
NSString *encodeStr = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[NSURL URLWithString:encodeStr];
NSLog(#" url is =%#",url);
But the url is showing nil value. It's not taking "encodeStr" value. How can I solve this problem.Please help me.
I tried with..
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:str] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
and also
strEncode=[strEncode stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Modified example from here:
#import <Foundation/Foundation.h>
// In case you're unfamiliar, this is a category, which allows us to add methods
// to an existing class, even if we didn't create it. It's a nice alternative
// to subclassing.
//
// In this case, we're extending NSString
#interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
#end
#implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool
{
NSString *raw = #"hi how#!#$%^^&*()_=+ r u <>,./ where r u";
// note also, that your string omits the '?' in the URL
NSString *url = [NSString stringWithFormat:#"http://google.com/API/index.php?action=listIt&data=%#",
[raw urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSURL *finalUrl = [NSURL URLWithString:url];
NSLog(#"%#", finalUrl);
}
}
Output:
http://google.com/API/index.php?action=listIt&data=hi%20how%40%21%23%24%25%5E%5E%26%2A%28%29_%3D%2B%20%20%20r%20u%20%3C%3E%2C.%2F%20where%20r%20u

IOS : NSString retrieving a substring from a string

Hey I am looking for a way to extract a string from another string. It could be any length and be in any part of the string so the usual methods don't work.
For example
http://bla.com/bla?id=%1234%&something=%888%
What I want to extract is from id=% to the next %.
Any idea's?
Use the rangeOfString method:
NSRange range = [string rangeOfString:#"id=%"];
if (range.location != NSNotFound)
{
//range.location is start of substring
//range.length is length of substring
}
You can then chop up the string using the substringWithRange:, substringFromIndex: and substringToIndex: methods to get the bits you want. Here's a solution to your specific problem:
NSString *param = nil;
NSRange start = [string rangeOfString:#"id=%"];
if (start.location != NSNotFound)
{
param = [string substringFromIndex:start.location + start.length];
NSRange end = [param rangeOfString:#"%"];
if (end.location != NSNotFound)
{
param = [param substringToIndex:end.location];
}
}
//param now contains your value (or nil if not found)
Alternatively, here's a general solution for extracting query parameters from a URL, which may be more useful if you need to do this several times:
- (NSDictionary *)URLQueryParameters:(NSURL *)URL
{
NSString *queryString = [URL query];
NSMutableDictionary *result = [NSMutableDictionary dictionary];
NSArray *parameters = [queryString componentsSeparatedByString:#"&"];
for (NSString *parameter in parameters)
{
NSArray *parts = [parameter componentsSeparatedByString:#"="];
if ([parts count] > 1)
{
NSString *key = [parts[0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *value = [parts[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
result[key] = value;
}
}
return result;
}
This doesn't strip the % characters from the values, but you can do that either with
NSString *value = [[value substringToIndex:[value length] - 1] substringFromIndex:1];
Or with something like
NSString *value = [value stringByReplacingOccurencesOfString:#"%" withString:#""];
UPDATE: As of iOS 8+ theres a built-in class called NSURLComponents that can automatically parse query parameters for you (NSURLComponents is available on iOS 7+, but the query parameter parsing feature isn't).
Try this
NSArray* foo = [#"10/04/2011" componentsSeparatedByString: #"/"];
NSString* day = [foo objectAtIndex: 0];

iphone+webservice

I have one web service but when i pass multiple word like new erra it will return 0 bytes in NSMutuabledata
my method is like
NSString *url = [NSString stringWithFormat:#"%#?url='%#'&word=%#",apiUrl,self.urlString,searchword];
NSMutableData *Data = [appDelegate initRequestWithPost:url withPostData:nil];
where searchword is new era
Thanks
I think you have to escape the url string. Try using somthing like this.
+(NSString *)escapeURL:(NSString *)text{
CFStringRef tmp=CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)text,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8 );
NSString * encodedString = (NSString *)tmp;
return encodedString;
}

iPhone parsing url for GET params

I have an string which is got from parsing an xml site.
http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500
I want to have an NSString function that will be able to parse the value of c.
Is there a default function or do i have to write it manually.
You could use Regular expression via RegExKit Lite:
http://regexkit.sourceforge.net/RegexKitLite/
Or you could separate the string into components (which is less nice):
NSString *url=#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray *comp1 = [url componentsSeparatedByString:#"?"];
NSString *query = [comp1 lastObject];
NSArray *queryElements = [query componentsSeparatedByString:#"&"];
for (NSString *element in queryElements) {
NSArray *keyVal = [element componentsSeparatedByString:#"="];
if (keyVal.count > 0) {
NSString *variableKey = [keyVal objectAtIndex:0];
NSString *value = (keyVal.count == 2) ? [keyVal lastObject] : nil;
}
}
I made a class that does this parsing for you using an NSScanner, as an answer to the same question a few days ago. You might find it useful.
You can easily use it like:
URLParser *parser = [[[URLParser alloc] initWithURLString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"] autorelease];
NSString *c = [parser valueForVariable:#"c"]; //c=500
Try the following:
NSURL *url = [NSURL URLWithString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"];
NSMutableString *parameterString = [NSMutableString stringWithFormat:#"{%#;}",[url parameterString]];
[parameterString replaceOccurrencesOfString:#"&" withString:#";"];
// Convert string into Dictionary
NSPropertyListFormat format;
NSString *error;
NSDictionary *paramDict = [NSPropertyListSerialization propertyListFromData:[parameterString dataUsingEncoding:NSUTF8StringEncoding] mutabilityOption: NSPropertyListImmutable format:&format errorDescription:&error];
// Now take the parameter you want
NSString *value = [paramDict valueForKey:#"c"];
Here is the native iOS approach using NSURLComponents and NSURLQueryItem classes:
NSString *theURLString = #"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray<NSURLQueryItem *> *theQueryItemsArray = [NSURLComponents componentsWithString:theURLString].queryItems;
for (NSURLQueryItem *theQueryItem in theQueryItemsArray)
{
NSLog(#"%# %#", theQueryItem.name, theQueryItem.value);
}