In my ios app when i try to add comments to vimeo videos using video.comment.addcomment, if the comment is only one word it is adding properly, but if it is more than one word it is saying an error that invalid signature.The code i used is:
NSString *new = [NSString stringWithString:commentis];
new = [new stringByReplacingOccurrencesOfString:#" " withString:#"+"];
NSString *url12 = #"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.comments.addComment&video_id=123456&comment_text=good";
url12 = [url12 stringByReplacingOccurrencesOfString:#"123456" withString:videoplaying];
url12 = [url12 stringByReplacingOccurrencesOfString:#"good" withString:new];
NSURL *urlinfo = [[NSURL alloc] initWithString:url12];
OAMutableURLRequest *request3 = [[OAMutableURLRequest alloc]initWithURL:urlinfo consumer:consumer token:tokenfi realm:nil signatureProvider:nil];
i dint understand the error.the json response i am getting is
{
err = {
code = 401;
expl = "The oauth_signature passed was not valid.";
msg = "Invalid signature";
};
"generated_in" = "0.0124";
stat = fail;
}
but if i give the comment as single word it is working fine.
Maybe it has something to do with the whitespace and the way you are executing your request. Make sure there is no whitespace in the URL you are formatting.
Replace the whitespace with the URL escape code right before you use the string to create a NSURL. Like this:
url12 = [url12 stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
Related
I would like to ask about filterExpression for AWSDynamoDBScanExpression.
Problem:
I want to scan db for all object in one table where one parameter (lets call it uniqueId) is one of the value stored in array (array of required uniqueIds).
For one object - it's easy to do with
AWSDynamoDBScanExpression *scanExpression = [[AWSDynamoDBScanExpression alloc] init];
scanExpression.expressionAttributeNames = #{
#"#P": [NSString stringWithFormat:#"%#", property]
};
scanExpression.filterExpression =#"#P = :val";
scanExpression.expressionAttributeValues = #{
#":val" : #"some uniqueID"
};
so in same logic i want to scan db for multi objects
AWSDynamoDBScanExpression *scanExpression = [[AWSDynamoDBScanExpression alloc] init];
scanExpression.expressionAttributeNames = #{
#"#P": [NSString stringWithFormat:#"%#", property]
};
scanExpression.filterExpression = <WHAT SHOULD BE HERE, WHAT EXPRESSION>;
scanExpression.expressionAttributeValues = #{
#":val" : [#"some unique id 1",
#"some unique id 2",
#"some unique id 3"]
};
Is any way to change scanExpression.filterExpression to achive this?
EDIT 1
No, I'm not sure that scan is the best solution. Actually query is best variant think.
The structure of table
#P = :val1 OR #P = :val2
make sense
EDIT2
This is some update:
AWSDynamoDBQueryExpression *query = [[AWSDynamoDBQueryExpression alloc] init];
NSMutableDictionary *dictionaryAttributes = [[NSMutableDictionary alloc] init];
NSString *expression = #"";
for (int i = 0; i < filteredHashValues.count; i++) {
NSString *variableName = [NSString stringWithFormat:#":val%i", i];
[dictionaryAttributes setValue:filteredHashValues[i] forKey:variableName];
expression = [expression stringByAppendingString:expression.length ? [NSString stringWithFormat:#"OR #P = %# " , variableName] : [NSString stringWithFormat:#"#P = %# " , variableName]];
}
query.indexName = #"uniqueId-index";
query.expressionAttributeNames = #{
#"#P": [NSString stringWithFormat:#"%#", #"uniqueId"]
};
query.filterExpression = expression;
query.expressionAttributeValues = dictionaryAttributes;
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
[[dynamoDBObjectMapper query:className expression:query] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
if (task.result) {
AWSDynamoDBPaginatedOutput *output = task.result;
}
return nil;
}];
But result
Printing description of expression:
#P = :val0 OR #P = :val1 OR #P = :val2 OR #P = :val3
Printing description of dictionaryAttributes:
{
":val0" = "8A93A3EA-9FB9-4396-BBF6-D0BD3CBE6BE5";
":val1" = "08533EBA-D3E5-406C-8CDE-03EECCCA801B";
":val2" = "954AE402-336E-423D-BF03-7E8AED1446FE";
":val3" = "F683BDF8-0507-4218-9927-9F14D470E593"; }
Printing description of task->_error: Error
`Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "(null)"
UserInfo={__type=com.amazon.coral.validate#ValidationException,
message=ExpressionAttributeValues contains invalid value: Supplied
AttributeValue is empty, must contain exactly one of the supported
datatypes for key :awsddbomhashvalueplaceholder}
looks like ExpressionAttributeValues is empty - am i doing all correct?
are you sure that you want to use a scan expression? this really consumes a lot of read capacity and can ruine your dynamodb performances: a scan reads you entire table and only THEN applies the filter and returns the values.
if you provide us with your actual dynamodb table structure we could maybe discuss another solution. For example a solution could be to create a global secondary index (if eventual consistent read is ok for you) or a local secondary index (along with its limitations), with a range key on your value to filter. This would allow you to use queries, which is much nicer and advised as of best practices.
That been said, you can just add conditions to your filter using AND and OR operators, resulting in sth similar to "#P = :val1 OR #P = :val2"
hope that helps
I am developing an iOS app and one of the things I need to do it to go over URLs and replace the first protocol section with my own custom protocol.
How can I delete the first few characters of a NSString before the "://"?
So for example I need convert the following:
http://website.com --> cstp://website.com
ftp://website.com --> oftp://website.com
https://website.com --> ctcps://website.com
The main problem I face, is that I can't just delete the first 'x' number of characters from the URL string. I have to detect how many characters there are till the "://" characters are reached.
So how can I count how many characters there are from that start of the string to the "://" characters?
Once I know this, I can then simply do the following to delete the characters:
int counter = ... number of characters ...
NSString *newAddress = [webURL substringFromIndex:counter];
Thanks for your time, Dan.
http://website.com is a URL, and http is the scheme part of the URL. Instead of string manipulation I would recommend to use the
NSURLComponents class which is made exactly for this purpose: inspect, create and modify URLs:
NSString *originalURL = #"http://website.com";
NSURLComponents *urlcomp = [[NSURLComponents alloc] initWithString:originalURL];
if ([urlcomp.scheme isEqualToString:#"http"]) {
urlcomp.scheme = #"cstp";
} else if ([urlcomp.scheme isEqualToString:#"ftp"]) {
urlcomp.scheme = #"otfp";
}
// ... handle remaining cases ...
NSString *modifiedURL = [urlcomp string];
NSLog(#"%#", modifiedURL); // cstp://website.com
If the number of cases grows then a dictionary mapping is easier to
manage:
NSDictionary *schemesMapping = #{
#"http" : #"cstp",
#"ftp" : #"otfp"
#"https" : #"ctcps" };
NSURLComponents *urlcomp = [[NSURLComponents alloc] initWithString:originalURL];
NSString *newScheme = schemesMapping[urlcomp.scheme];
if (newScheme != nil) {
urlcomp.scheme = newScheme;
}
NSString *modifiedURL = [urlcomp string];
You can use:
NSRange range = [urlString rangeOfString:#"://"];
range.location will give you the first index from where the "://" starts and you can use it as:
NSString *newAddress = [urlString substringFromIndex:range.location];
and append your prefix:
NSString *finalAddress = [NSString stringWithFormat:#"%#%#", prefixString, newAddress];
My code:
NSString *urlString = [NSString stringWithFormat:#"%#%#%#%#", #"http://api.search.live.net/json.aspx?Appid=am hiding the appid &query=",text,#"&sources=web&web.offset=",offvalue];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
The JSON response:
SearchResponse = {
Errors = (
{
Code = 1002;
HelpUrl = "http://msdn.microsoft.com/en-us/library/dd251042.aspx";
Message = "Parameter has invalid value.";
Parameter = "SearchRequest.AppId";
Value = " am hiding the value";
}
);
Query = {
SearchTerms = iphone;
};
Version = "2.2";
};
}
What wrong am I doing here.Can anyone please rectify my query??How to use version 2.2 of the bing API
What is the value of 'text', is this one word or multiple words? You'll need to perform URL_Encode on the parameter 'text' in order to have a valid URL.
See Objective-C and Swift URL encoding
Be sure only to have the URL_Encoding on the text-object and not on the whole URL, otherwise "http://" will be encoded as well, resulting in an invalid URL as well
Eg a space should be %20 , you can verify this by adding a NSLog of the URL
It looks like you entered the wrong AppID judging from.
Parameter = "SearchRequest.AppId";
Make sure that the AppID matches the appID that they assigned your app with the service.
Also (and this sometimes randomly causes issues for me) make sure you put a / at the end of the URL String.
I'm unable to open a URL into UIWebView so I've seached & found that I need to encode URL, so I tried to encode it but, I've facing problem in URL encoding : My URL is http://somedomain.com/data/Témp%20Page%20-%20Open.html (It's not real URL).
I'm concerned with %20 that I tried to replace using stringByReplacingOccuranceOfString:#"" withString:#"" , it give me the URL I wanted like http://somedomain.com/data/Témp Page - Open.html However its not opening in UIWebView but amazingly it opens in Safari & FireFox perfect. Even I open unencoded URL its automatically converts and open the page I'm looking for.
I've google for URL encoding & it points me to different results I already checked but no results help me out!! I tried different functions answers in different URL encoding question but it just changed all special characters and make my URL like, http%3A%2F%2Fsomedomain.com%2Fdata%2FT... which can't open in UIWebView and even in any browser.
It gives the following Error Log in UIWebView delegate
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { }
Error Code : 101
& Description : Error Domain=WebKitErrorDomain Code=101 "The operation couldn’t be completed. (WebKitErrorDomain error 101.)" UserInfo=0x6e4cf60 {}
The answer #Dhaval Vaishnani provided is only partially correct. This method treats the ?, = and & characters as not to be encoded, since they're valid in an URL. Thus, to encode an arbitrary string to be safely used as a part of an URL, you can't use this method. Instead you have to fall back to using CoreFoundation and CFURLRef:
NSString *unsafeString = #"this &string= confuses ? the InTeRwEbZ";
CFStringRef safeString = CFURLCreateStringByAddingPercentEscapes (
NULL,
(CFStringRef)unsafeString,
NULL,
CFSTR("/%&=?$#+-~#<>|\\*,.()[]{}^!"),
kCFStringEncodingUTF8
);
Don't forget to dispose of the ownership of the resulting string using CFRelease(safeString);.
Also, it seems that despite the title, OP is looking for decoding and not encoding a string. CFURLRef has another, similar function call to be used for that:
NSString *escapedString = #"%32%65BCDEFGH";
CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding (
NULL,
(CFStringRef)escapedString,
CFSTR(""),
kCFStringEncodingUTF8
);
Again, don't forget proper memory management.
I did some tests and I think the problem is not really with the UIWebView but instead that NSURL won't accept the URL because of the é in "Témp" is not encoded properly. This will cause +[NSURLRequest requestWithURL:] and -[NSURL URLWithString:] to return nil as the string contains a malformed URL. I guess that you then end up using a nil request with -[UIViewWeb loadRequest:] which is no good.
Example:
NSLog(#"URL with é: %#", [NSURL URLWithString:#"http://host/Témp"]);
NSLog(#"URL with encoded é: %#", [NSURL URLWithString:#"http://host/T%C3%A9mp"]);
Output:
2012-10-02 12:02:56.366 test[73164:c07] URL with é: (null)
2012-10-02 12:02:56.368 test[73164:c07] URL with encoded é: http://host/T%C3%A9mp
If you really really want to borrow the graceful handling of malformed URLs that WebKit has and don't want to implement it yourself you can do something like this but it is very ugly:
UIWebView *webView = [[[UIWebView alloc]
initWithFrame:self.view.frame]
autorelease];
NSString *url = #"http://www.httpdump.com/texis/browserinfo/Témp.html";
[webView loadHTMLString:[NSString stringWithFormat:
#"<script>window.location=%#;</script>",
[[[NSString alloc]
initWithData:[NSJSONSerialization
dataWithJSONObject:url
options:NSJSONReadingAllowFragments
error:NULL]
encoding:NSUTF8StringEncoding]
autorelease]]
baseURL:nil];
The most straightforward way is to use:
NSString *encodedString = [rawString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
iDhaval was close, but he was doing it the other way around (decoding instead of encoding).
Anand's way would work, but you'll most likely have to replace more characters than spaces and new lines. See the reference here:
http://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters
Hope that helps.
It's very simple to encode the URL in iPhone. It is as following
NSString* strURL = #"http://somedomain.com/data/Témp Page - Open.html";
NSURL* url = [NSURL URLWithString:[strURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
It's a perfect way to encode the URL, I am using it and it's perfectly work with me.
Hope it will help you!!!
This may useful to someone who's reach to this question for URL encoding, as my question likely different which has been solved and accepted, this is the way I used to do encoding,
-(NSString *)encodeURL:(NSString *)urlString
{
CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)urlString, NULL, CFSTR("!*'();:#&=+#,/?#[]"), kCFStringEncodingUTF8);
return (NSString *)CFBridgingRelease(newString);
}
You can try this
NSString *url = #"http://www.abc.com/param=Hi how are you";
NSString* encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
I think this will work for you
[strUrl stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]
the Native method for URL Encoding.
Swift 4.x
let originalString = "https://www.somedomain.com/folder/some cool file.jpg"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString!)
You probably need to break the URL down into it's constituent parts and then URL encode the host and path but not the scheme. Then put it back together again.
Create an NSURL with the string and then use the methods on it such as host, scheme, path, query, etc to pull it apart. Then use CFURLCreateStringByAddingPercentEscapes to encode the parts and then you can put them back together again into a new NSURL.
can you please Try this out.
//yourURL contains your Encoded URL
yourURL = [yourURL stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
yourURL = [yourURL stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSLog(#"Keyword:%# is this",yourURL);
I am not sure,but I have solved using this in my case.
Hope this will solve yours.
I'm looking for a way to make sure a string can be used as a file name under iOS. I'm currently in the section of the code that deletes incompatible characters. I'm wondering if I'm doing it right.
NSString *filename = #"A file name";
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet controlCharacterSet]];
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet newlineCharacterSet]];
I'm also wondering if there's already a method that validates a string as a file name.
Thank you for your advice!
Use RegEx:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[^a-zA-Z0-9_]+" options:0 error:nil];
filename = [regex stringByReplacingMatchesInString:filename options:0 range:NSMakeRange(0, filename.length) withTemplate:#"-"];
I find this to be cleaner and probably much more performant. This is based on Angel Naydenov's solution, but first constructing Character set with all invalid characters and then calling components(separatedBy:) just once.
Swift 3 & 4
var invalidCharacters = CharacterSet(charactersIn: ":/")
invalidCharacters.formUnion(.newlines)
invalidCharacters.formUnion(.illegalCharacters)
invalidCharacters.formUnion(.controlCharacters)
let newFilename = originalFilename
.components(separatedBy: invalidCharacters)
.joined(separator: "")
Swift 2
let invalidCharacters = NSMutableCharacterSet(charactersInString: ":/")
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.newlineCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.illegalCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.controlCharacterSet())
let filename = originalFilename
.componentsSeparatedByCharactersInSet(invalidCharacters)
.joinWithSeparator("")
First of all, you're using the wrong method. Trimming the string will only remove characters in the beginning and the end of the string.
What you're looking for is something more like:
fileName = [fileName stringByReplacingOccurrencesOfString:#"/" withString:#"_"];
However, that's a suboptimal solution, since you'll have to do that for every character you want to exclude, so maybe you want to keep looking or write you're own method for manipulating the string.
iOS is UNIX based and as such I suppose it supports almost any characters in filenames. UNIX allows white spaces, <, >, |, \, :, (, ), &, ;, as well as wildcards such as ? and *, to be quoted or escaped using \ symbol. However I wouldn't use any of those characters in my filenames. In fact, I would restrict the characters in my filenames to 'a'-'z', '0'-'9', '_' and '.'.
As I did not see a list with allowed characters in this question but the question wanted a list with such characters I am adding a bit more details on this topic.
First we need to know what is the file system that iOS devices use. Using multiple online sources this seems to be HFSX which is the HFS+ case sensitive version. And including one link here for reference: https://apple.stackexchange.com/questions/83671/what-filesystem-does-ios-use
Now that we know what the file system is we can look for what characters are not allowed. And these seem to be: colon (:) and slash (/). Here is a link for reference: http://www.comentum.com/File-Systems-HFS-FAT-UFS.html
Having this information and what others have written in this thread my personal preference for removing not allowed characters from file names is the following Swift code:
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()))
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.illegalCharacterSet()))
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.controlCharacterSet()))
filename = "-".join(filename.componentsSeparatedByString(":"))
filename = "-".join(filename.componentsSeparatedByString("/"))
The reason I am not preferring the RegEx approach is that it seems too restrictive to me. I do not want to restrict my users only to Latin characters. They may as well wish to use some Chinese, Cyrillic or whatever else they like.
Happy coding!
I've had to save remote files locally with filenames containing other characters than basic alpha-numeric characters. I use the method below to strip out potential invalid characters, ensuring it's a valid filename for the filesystem when generating a NSURL using URLWithString:
filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:#"" ];
filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet illegalCharacterSet]] componentsJoinedByString:#"" ];
filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet symbolCharacterSet]] componentsJoinedByString:#"" ];
fileURLString = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
fileURL = [NSURL URLWithString:fileURLString];
You may also want to test for collision errors first using:
[[NSFileManager defaultManager] fileExistsAtPath:[fileURL absoluteString]]
This String extension (Swift 4.2) will help convert an invalid iOS file name to a valid iOS file name.
extension String {
func convertToValidFileName() -> String {
let invalidFileNameCharactersRegex = "[^a-zA-Z0-9_]+"
let fullRange = startIndex..<endIndex
let validName = replacingOccurrences(of: invalidFileNameCharactersRegex,
with: "-",
options: .regularExpression,
range: fullRange)
return validName
}
}
For example
"name.name?/!!23$$#1asd".convertToValudFileName() // "name-name-23-1asd"
"!Hello.312,^%-0//\r\r".convertToValidFileName() // "-Hello-312-0-"
"/foo/bar/pop?soda=yes|please".convertToValidFileName() // "-foo-bar-pop-soda-yes-please"
I'm pretty happy with this solution:
NSString *testString = #"This*is::/legal.😀,?縦書き 123";
NSString *result = [[[testString componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"length > 0"]] componentsJoinedByString:#"-"];
Output:
"This-is-legal-縦書き-123"
What is this sorcery?
Let me break it up into multiple lines so it's clear what's going on:
NSString *testString = #"This*is::/legal.😀,?縦書き 123";
// Get a character set for everything that's NOT alphanumeric.
NSCharacterSet *nonAlphanumericCharacterSet = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
// Split the string on each non-alphanumeric character, thus removing them.
NSArray *cleanedUpComponentsWithBlanks = [testString componentsSeparatedByCharactersInSet:nonAlphanumericCharacterSet];
// Filter out empty strings ("length" is a KVO-compliant property that the predicate can call on each NSString in the array).
NSArray *cleanedUpComponentsWithoutBlanks = [cleanedUpComponentsWithBlanks filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"length > 0"]];
// Put the components back together and join them with a "-".
NSString *result = [cleanedUpComponentsWithoutBlanks componentsJoinedByString:#"-"];
Enjoy!
Swift 4 Version
Added by john-pang on 2021-09-01 with Swift version:
let testString = "This*is::/legal.😀,?縦書き 123"
// Get a character set for everything that's NOT alphanumeric.
let nonAlphanumericCharacterSet = CharacterSet.alphanumerics.inverted
// Split the string on each non-alphanumeric character, thus removing them.
let cleanedUpComponentsWithBlanks = testString.components(separatedBy: nonAlphanumericCharacterSet)
// Filter out empty strings ("length" is a KVO-compliant property that the predicate can call on each NSString in the array).
let cleanedUpComponentsWithoutBlanks = cleanedUpComponentsWithBlanks.filter { $0.length > 0 }
// Put the components back together and join them with a "-".
let result = cleanedUpComponentsWithoutBlanks.joined(separator: "_")
I came up with the following solution. Works nice so far.
import Foundation
extension String {
func removeUnsupportedCharactersForFileName() -> String {
var cleanString = self
["?", "/", "\\", "*"].forEach {
cleanString = cleanString.replacingOccurrences(of: $0, with: "-")
}
return cleanString
}
}
let a = "***???foo.png"
let validString = a.removeUnsupportedCharactersForFileName()
Base on Marian Answers, here is a string extension to remove any unwanted characters.
extension String {
func stripCharacters() -> String {
var invalidCharacters = CharacterSet(charactersIn: ":/")
invalidCharacters.formUnion(.newlines)
invalidCharacters.formUnion(.illegalCharacters)
invalidCharacters.formUnion(.controlCharacters)
let newString = self
.components(separatedBy: invalidCharacters)
.joined(separator: "_")
return newString
}
}
Example:
let fileName = "Man(lop23/45"
let newFileName = fileName.stripCharacters()
print(newFileName)
Swift 5 extension:
I wanted to remove emojis as well and in windows \ is also an invalid character. So I added symbols charset and backslash \ as well.
extension String {
var validFilename: String {
let invalidCharsets = CharacterSet(charactersIn: ":/\\")
.union(.illegalCharacters)
.union(.controlCharacters)
.union(.symbols)
.union(.newlines)
return self.components(separatedBy: invalidCharsets).joined()
}
}