Get filename from Content-Disposition header - iphone

I'm currently checking for this header and if it's available, I'll try to get the filename from it. Question is, what is the best method to retrieve it? I understand that Content-Disposition header may appear with different parameters. Examples below:
Content-Disposition = "inline; filename=sample-file-123.pdf"
Content-Disposition = "attachment; filename="123.zip""
I'm only interested to get the filename.

There is a dedicated API for this: URLResponse.suggestedFilename
So if you are getting your header from a URLResponse you just call
let filename: String = response.suggestedFilename ?? "default"
and you're done. Note that despite what the documentation says, the return value is optional so you have to provide a default or force unwrap if you dare (I wouldn't).
From the documentation:
The method first checks if the server has specified a filename using the
content disposition header. If no valid filename is specified using that mechanism,
this method checks the last path component of the URL. If no valid filename can be
obtained using the last path component, this method uses the URL's host as the filename.
If the URL's host can't be converted to a valid filename, the filename "unknown" is used.
In mose cases, this method appends the proper file extension based on the MIME type.
This method always returns a valid filename.

I would do something along the lines of this:
- (NSString *)getFilenameFrom:(NSString *)string {
NSRange startRange = [string rangeOfString:#"filename="];
if (startRange.location != NSNotFound && startRange.length != NSNotFound) {
int filenameStart = startRange.location + startRange.length;
NSRange endRange = [string rangeOfString:#" " options:NSLiteralSearch range:NSMakeRange(filenameStart, [string length] - filenameStart)];
int filenameLength = 0;
if (endRange.location != NSNotFound && endRange.length != NSNotFound) {
filenameLength = endRange.location - filenameStart;
} else {
filenameLength = [string length] - filenameStart;
}
return [string substringWithRange:NSMakeRange(filenameStart, filenameLength)];
}
return nil; //or return #"", whatever you like
}
You will have to check it as i made this in the browser (dont have access to xcode atm).

+ (NSString *)filenameFromContentDispositionHeader:(NSString *)contentDispositionHeader {
NSString *pattern = #"filename=\"(.*)\"";
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
NSTextCheckingResult *result =
[regex firstMatchInString:contentDispositionHeader
options:0
range:NSMakeRange(0, contentDispositionHeader.length)];
NSRange resultRange = [result rangeAtIndex:0];
if (resultRange.location == NSNotFound) {
return nil;
} else {
return [contentDispositionHeader substringWithRange:
NSMakeRange(resultRange.location + 10, resultRange.length - 11)];
}
}
Note that you'll need to modify the pattern if you can't be sure the filename is surrounded in double-quotes.

Related

iOS rangeOfString can't locate the string that is definitely there

I am writing code in objective-c. I would like to extract a url from a string.
Here is my code:
NSMutableString *oneContent = [[latestPosts objectAtIndex:i] objectForKey:#"content"];
NSLog(#"%#", oneContent);//no problem
NSString *string = #"http";
if ([oneContent rangeOfString:string].location == NSNotFound) {
NSLog(#"string does not contain substring");
} else {
NSLog(#"string contains substring!");
}
As you can see, I want to extract a url from the oneContent string, and I have checked that oneContent definitely contains "http", but why does the result show nothing?
Is there some better way to extract the url?
Check oneContent or the actual code you are running.
This works:
NSMutableString *oneContent = [#"asdhttpqwe" mutableCopy];
NSLog(#"%#", oneContent);//no problem
NSString *string = #"http";
if ([oneContent rangeOfString:string].location == NSNotFound) {
NSLog(#"string does not contain substring");
} else {
NSLog(#"string contains substring!");
}
NSLog output:
Untitled[5911:707] asdhttpqwe
Untitled[5911:707] string contains substring!
It is probably best not to use a Mutable string unless there is some substantial reason to do so.
I would suggest using NSScanner.

NSString value validation in iOS

This simple validation method for NSString makes trouble.
I have an NSString value and I want to validate the string, i.e, if the string contains only 'a to z' (or) 'A to Z' (or) '1 to 9' (or) '#,!,&' then the string is valid. If the string contains any other values then this the NSString is invalid, how can i validate this..?
As example:
Valid:
NSString *str="aHrt#2"; // something like this
Invalid:
NSString *str="..gS$"; // Like this
Try using character sets:
NSMutableCharacterSet *set = [NSMutableCharacterSet characterSetWithCharactersInString:#"#!&"];
[set formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
if ([string rangeOfCharacterFromSet:[set invertedSet]].location == NSNotFound) {
// contains a-z, A-Z, 0-9 and &#! only - valid
} else {
// invalid
}
I would do something using stringByTrimmingCharactersInSet
Create an NSCharacterSet containing all valid characters, then trim those characters from the test string, if the string is now empty it is valid, if there are any characters left over, it is invalid
NSCharacterSet *validCharacters = [NSCharacterSet characterSetWithCharactersInString:#"myvalidchars"];
NSString *trimmedString = [testString stringByTrimmingCharactersInSet:validCharachters];
BOOL valid = [trimmedString length] == 0;
Edit:
If you want to control the characters that can be entered into a text field, use textField:shouldChangeCharactersInRange:replacementString: in UITextFieldDelegate
here the testString variable becomes the proposed string and you return YES if there are no invalid characters
The NSPredicate class is what you want
More info about predicate programming. Basically you want "self matches" (your regular expression). After that you can use the evaluateWithObject: method.
EDIT Easier way: (nevermind, as I am editing it wattson posted what I was going to)
You can use the class NSRegularExpression to do this.
https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html
You can also use NSRegularExpression to search your NSString, if it contains only the valid characters (or vice versa).
More info:
Search through NSString using Regular Expression
Use regular expression to find/replace substring in NSString
- (BOOL)validation:(NSString *)string
{
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:#"1234567890abcdefghik"] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return ([string isEqualToString:filtered]);
}
In your button action:
-(IBAction)ButtonPress{
if ([self validation:activity.text]) {
NSLog(#"Macth here");
}
else {
NSLog(#"Not Match here");
}
}
Replace this "1234567890abcdefghik" with your letters with which you want to match
+(BOOL) validateString: (NSString *) string
{
NSString *regex = #"[A-Z0-9a-z#!&]";
NSPredicate *test = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
BOOL isValid = [test evaluateWithObject:string];
return isValid;
}
You can simply do it using NSMutableCharacterSet
NSMutableCharacterSet *charactersToKeep = [NSMutableCharacterSet alphanumericCharacterSet];
[charactersToKeep addCharactersInString:#"#?!"];
NSCharacterSet *charactersToRemove = [charactersToKeep invertedSet]
NSString *trimmed = [ str componentsSeparatedByCharactersInSet:charactersToRemove];
if([trimmed length] != 0)
{
//invalid string
}
Reference NSCharacterSet
You can use regex. If every thing fails use brute force like
unichar c[yourString.length];
NSRange raneg={0,2};
[yourString getCharacters:c range:raneg];
// now in for loop
for(int i=0;i<yourString.length;i++)
{
if((c[i]>='A'&&c[i]<='Z')&&(c[i]=='#'||c[i]=='!'||c[i]=='&'))
{
//not the best or most efficient way but will work till you write your regex:P
}
}

going to fetch a value from xml response when going to parse but i am fail to get value

Below code is the response from the server:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SendCardDetailsResponse xmlns="http://tempuri.org/"><SendCardDetailsResult><ROOT xmlns=""><DocumentElement><res-auth><auth-data count='1' ><**attribute name='OTP1'** length='6' type='N' label='OTP' prompt='Please enter OTP as send to your mobile.'/></auth-data></res-auth></DocumentElement></ROOT></SendCardDetailsResult></SendCardDetailsResponse></soap:Body></soap:Envelope>
I have to fetch attribute name which is 'OTP1'
how can I get value of attribute name
any help will be appreciable
I would use smth like this:
-(NSString*) getAttribute{
NSString *attribute = #"";
NSString *xmlString = #"";//put the XML in this NSString
int endOfSrc = [xmlString rangeOfString:#"\"><attribute name='"].location+[xmlString rangeOfString:#"\"><attribute name='"].length;
int borderPos = [xmlString rangeOfString:#"' length='"].location;
if(borderPos != NSNotFound){
NSRange range;
range.location = endOfSrc;
range.length = borderPos - endOfSrc;
attribute = [xmlString substringWithRange:range];
return attribute;
}
return #" ";
}
Nothing hard here, if some questions about the code appear, just see the documentation for the functions i've used here.
maybe there are more efficient ways, dunno. It works like a charm for me.

Replace string by an image

I am trying to use emoticons for my chat application. I am comparing the string I get or I send with a local string. If I am get the result as true I want to replace the string with an image. For that matter I am not using may emoticons.
I am trying this:
NSRange textRange;
textRange =[text rangeOfString:#":)"];
if(textRange.location != NSNotFound)
{
//Does contain the substring
}
else
{
// replace string with image.
}
But I am not able to figure out how to replace image at the string position.
I assumed you want to put smileys.
So you can try this :
NSRange range = {NSNotFound, 0};
NSString *s = #"This is a smiley :) face";
range.location = 0;
range.length = [s length];
s = [s stringByReplacingOccurrencesOfString:#":)"
withString:#"\ue415"
options:NSCaseInsensitiveSearch
range:range];
For more detail please refer this link.

How to check if a string contains an URL

i have text message and I want to check whether it is containing text "http" or URL exists in that.
How will I check it?
NSString *string = #"xxx http://someaddress.com";
NSString *substring = #"http:";
Case sensitive example:
NSRange textRange = [string rangeOfString:substring];
if(textRange.location != NSNotFound){
//Does contain the substring
}else{
//Does not contain the substring
}
Case insensitive example:
NSRange textRange = [[string lowercaseString] rangeOfString:[substring lowercaseString]];
if(textRange.location != NSNotFound){
//Does contain the substring
}else{
//Does not contain the substring
}
#Cyprian offers a good option.
You could also consider using a NSRegularExpression which would give you far more flexibility assuming that's what you need, e.g. if you wanted to match http:// and https://.
Url usually has http or https in it
You can use your custom method containsString to check for those strings.
- (BOOL)containsString:(NSString *)string {
return [self containsString:string caseSensitive:NO];
}
- (BOOL)containsString:(NSString*)string caseSensitive:(BOOL)caseSensitive {
BOOL contains = NO;
if (![NSString isNilOrEmpty:self] && ![NSString isNilOrEmpty:string]) {
NSRange range;
if (!caseSensitive) {
range = [self rangeOfString:string options:NSCaseInsensitiveSearch];
} else {
range = [self rangeOfString:string];
}
contains = (range.location != NSNotFound);
}
return contains;
}
Example :
[yourString containsString:#"http"]
[yourString containsString:#"https"]