Objective C Find a HTML input line in NSData - html

I am trying to read in a website and find a input line from the code. But can't figure out how to find the a line of data.
Trying to find the line:
<input type="hidden" name="_token" value="01234abcABC">
Here is my code.
NSURL *nsurl = [NSURL URLWithString:#"https://www.mywebsite.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsurl];
[request setTimeoutInterval:10];
[request setHTTPMethod:#"GET"];
NSHTTPURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
if(data == nil)
return;
// Need to loop through the data line by line to find this line?

Regular expressions can be your best friends.
// Add a NUL byte so that the data is a valid C string
NSMutableData *mutableData = [data mutableCopy];
char nul = '\0';
[mutableData appendBytes:&nul length:1];
// Wrap the data as a string
NSString *dataStr = [NSString stringWithUTF8String:data.bytes];
// Find the target string within the data string
NSRange inputTagRange = [dataStr rangeOfString:
#"<input\\s+type=\"hidden\"\\s+name=\"_token\"\\s+value=\"[0-9a-zA-Z]+\">"
options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
// Expand the target range to cover each line that the target spans
NSRange inputTagLineRange = [dataStr lineRangeForRange:inputTagRange];
See it working here.

Related

Objective C String to JSON formatting

Quick disclaimer. I've programmed Java for years but this is the first Objective C I've ever written.
I've written some code which almost unfortunately works but frankly hurts my eyes with the number of lines of code and quality. Basically looking for the right way to convert the original string:
<TUHandle 0x280479f50 type=PhoneNumber, value=07700000000, normalizedValue=(null), isoCountryCode=(null)>
Into JSON (ignoring the TUHandle 0x280479f50) part which I don't need:
{"value": "07700000000",
"normalizedValue": "(null)",
"type": "PhoneNumber",
"isoCountryCode": "(null)"}
Line breaks and indents are NOT important, only that this is valid JSON
//Format of string
//<TUHandle 0x280479f50 type=PhoneNumber, value=07700000000, normalizedValue=(null), isoCountryCode=(null)>
NSString *original = [NSString stringWithFormat:#"%#", hand];
//Trim off unused stuff
NSRange startKeyValues = [original rangeOfString:#"type="];
NSRange endKeyValues = [original rangeOfString:#">"];
NSRange rangeOfString = NSMakeRange(startKeyValues.location, endKeyValues.location - startKeyValues.location);
NSString *keysValues = [original substringWithRange:rangeOfString];
//Create a dictionary to hold the key values
NSMutableDictionary *dict = [[NSMutableDictionary alloc]initWithCapacity:10];
//Split the keysValuesstring
NSArray *items = [keysValues componentsSeparatedByString:#","];
for (NSString* o in items)
{
//Create key value pairs
NSArray *item = [o componentsSeparatedByString:#"="];
NSString *key=[item objectAtIndex:0];
NSString *value=[item objectAtIndex:1];
[dict setObject:value forKey:key];
}
[dict setObject:currentUUID forKey:#"uid"];
//Convert to Json Object
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
Any tips which would make this look a hell of a lot less clunky?
Depending on what parts of the format you're comfortable with hardcoding, this may serve.
It assumes that only parts of the input string that look like "x=y" go into the json, and cuts off the last character from y's value, since that's either a "," or the trailing ">".
- (void) tuhandleToJSON {
NSString* input = #"<TUHandle 0x280479f50 type=PhoneNumber, value=07700000000, normalizedValue=(null), isoCountryCode=(null)>";
NSMutableDictionary<NSString*, NSString*>* dict = [NSMutableDictionary dictionary];
NSArray* tokens = [input componentsSeparatedByString:#" "];
for (NSString* token in tokens) {
NSArray<NSString*>* parts = [token componentsSeparatedByString:#"="];
if (parts.count != 2) {
continue;
}
NSString* key = parts[0];
NSString* value = parts[1];
NSUInteger index = value.length - 1;
dict[key] = [value substringToIndex:index];
}
NSError* error;
NSData* data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
NSString* json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", json);
}

NSURLSession POST request return HTML webpage code

I am trying to submit user input to a webpage and then retrieve returned data. This webpage takes a person's name and returns his/her information from a database. I tried to make a POST request when user clicks a button then send user's input to that webpage. But when I print out returned data, it's just the html source code of that webpage, only without javaScript. How can I change/add the below function to get the person's information page? I've spent lots of time but still can't figure it out. Please help me! Thank you!
-(void) sendHTTPPost{
NSString* input = nameTextField.text;
//1
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://find.pitt.edu"]];
[req setHTTPMethod:#"POST"];
//2
NSData* postData = [input dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
//3
NSString *postLength = [NSString stringWithFormat:#"%lu",(unsigned long)[postData length]];
[req setValue:postLength forHTTPHeaderField:#"Content-Length"];
[req setValue:#"text/html" forHTTPHeaderField:#"Content-type"];
[req setHTTPBody:postData];
//4
NSURLSession *session = [NSURLSession sharedSession];
//5
NSURLSessionDataTask *task = [session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// Do something with response data here - convert to JSON, check if error exists, etc....
if(error != nil){
NSLog(#"error: %#", error);
}
else{
NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", str);
NSLog(#"response = %#", response);
}
}];
[task resume];
}
It is unlikely that the POST body is supposed to contain only the value. Chances are, it should contain
key=value&key2=value2&key3=value3...
where key is the name of the input, and value is the value of that input, in a URL-encoded format. (See "Encoding URL Data" in URL Session Programming Guide for details on how to URL-encode the values.)

IOS Regular parse HTML

i want to parse html content into Dictionary
EDIT:
I need to parse just simple HTML, don't need to consider the complex situation.
WEB side: when I was in the system input information, using the HTML editor. But fix the old WEB system , need to modify the place more, so temporary use parsing HTML mode in the current version of the APP。
END:
Html just like this:
<p>hahaha</p><img src="aaaa.jpg"/>heihei<img src="bbb.jpg"/>guagua
i want the result is:
text hahaha
img aaaa.jpg
text heihei
img bbb.jpg
text guagua
my code is:
//<p>hahaha</p><img src="aaaa.jpg"/>heihei<img src="bbb.jpg"/>guagua
//for this
//NSArray = {0,1,2,3,4}
//NSDictionary{Sort-Key,V}={{0,{text,hahaha}},{1,{img,aaaa.jpg}},{2,{text,heihei}},{3, {img,bbb.jpg}},{4,{text,guagua}}}
-(NSArray*)RegularExpression:(NSString *)str dic:(NSMutableDictionary**)dic
{
if(str == nil) return nil;
NSString *pgnText = str;
NSString* tags=#"<[p|div].*?>(.*?)</[p|div].*?>";
NSString *regTags = tags;
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regTags options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *matches = [regex matchesInString:pgnText
options:0
range:NSMakeRange(0, [pgnText length])];
NSMutableArray* arrItems = [[NSMutableArray alloc] initWithCapacity:[matches count]];
if(matches.count >0){
for (NSTextCheckingResult *match in matches) {
NSString *tagValue = [pgnText substringWithRange:[match rangeAtIndex:1]];
NSArray* arr = [self RegularExpression:tagValue dic:dic];
[arrItems addObjectsFromArray:arr];
}
}
else{
NSString* regTags2 = #".*?<img.*?src.*?=.*?[\"|”](.*?)[\"|”].*?/>";
NSRegularExpression *regex2 = [NSRegularExpression regularExpressionWithPattern:regTags2 options:NSRegularExpressionCaseInsensitive|NSRegularExpressionAnchorsMatchLines error:&error];
pgnText = str;
NSArray *matches2 = [regex2 matchesInString:pgnText
options:0
range:NSMakeRange(0, [pgnText length])];
for (NSTextCheckingResult *match in matches2) {
NSString *tagValue = [pgnText substringWithRange:[match rangeAtIndex:1]];
NSLog(#"%#",tagValue);
}
}
return [arrItems autorelease];
}
Who has done similar function?
Keys in a dictionary must be unique. You cannot have more than one "img" key.
Check out this SO question: Objective-C DOM XML parser for iPhone

getting the value from an NSDictionary of NSDictionaries

I am doing a native objC app. ios5
I want to parse a JSON file in the local bundle.
And read each item individually.
To follow is a sample of my JSON file, followed by the code I have working.
I also have explanation of what I think is going on, and the sample code that I need to get assistance with. You are welcome to correct my interpretation as well.
=========================================================================
{"a":[
{"b":{"Q01":"A01","Q02":"B01","Q03":"C01","Q04":"D01","Q05":"E01","Q06":"X","C1":"NR","CABG":"NR","PCI":"NR"}},
{"b":{"Q01":"A01","Q02":"B01","Q03":"C01","Q04":"D01","Q05":"E02","Q06":"X","C1":"I","C1IND":"20","C1SCORE":"3","CABG":"NR","PCI":"NR"}},
{"b":{"Q01":"A01","Q02":"B01","Q03":"C01","Q04":"D01","Q05":"E03","Q06":"X","C1":"NR","CABG":"NR","PCI":"NR"}},
{"b":{"Q01":"A01","Q02":"B01","Q03":"C01","Q04":"D01","Q05":"E04","Q06":"X","C1":"NR","CABG":"NR","PCI":"NR"}},
{"b":{"Q01":"A01","Q02":"B01","Q03":"C01","Q04":"D01","Q05":"E05","Q06":"X","C1":"NR","CABG":"NR","PCI":"NR"}}
]}
My code looks like:
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"nonacs" ofType:#"json"];
NSError* error = nil;
NSData *jsonData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];
if (jsonData) {
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
if (error) {
NSLog(#"error is %#", [error localizedDescription]);
// Handle Error and return
return;
}
//NSArray *keys = [jsonObjects allKeys];
// not necessary becuase I know the Root key is a single "a"
NSString* jsonString = [NSString stringWithFormat:#"%#",[jsonObjects objectForKey:#"a"]];
tLabel01.text = [NSString stringWithFormat:#"jsonData Length is = %d", [jsonData length]];
NSDictionary* dict01 = [[NSDictionary alloc] initWithDictionary:jsonObjects];
l2.text = [NSString stringWithFormat:#"dict01 length = %d", dict01.count];
NSDictionary* dict02 =[[NSDictionary alloc] initWithDictionary:dict01];
l3.text = [NSString stringWithFormat:#"dict2.length = %d", dict02.count];
//NSArray* array01 = [[NSArray alloc] initWithObjects:dict01, nil];
//NSArray *allvalues = [jsonObjects allValues];
//NSArray *allvalues = [[jsonObjects initWithContentsOf ] allValues];
//l3.text = [NSString stringWithFormat:#"allvalues.count = %d", allvalues.count];
//NSDictionary *dictB = [dict01 objectForKey:#"b"];
//l3.text = [NSString stringWithFormat:#"dictB.count = %d", dictB.count];
l3.text = [NSString stringWithFormat:#"jsonObject count = %d", [[jsonObjects objectForKey:#"a"] count]];
// this works really well... except it returned 1700, and there should only be 1550
//l4.text = #"nada";
//[[jsonObjects objectForKey:#"a"] count]]
NSArray *array = [jsonObjects objectForKey:#"a"];
NSArray *arrayVariable = [array objectAtIndex:0];
//l4.text = [NSString stringWithFormat:#"Q01 = %#", [arrayVariable objectForKey: #"Q01"]];
//l4.text =[NSString stringWithFormat:#"arrayVariable count = %d", arrayVariable.count];
NSArray *arrayb = [jsonObjects objectForKey:#"b"];
l4.text = [NSString stringWithFormat:#"arrayb count = %d", arrayb.count];
bTV01.text = jsonString;
};
=============================================================================
The root Object is an NSDictionary with single Key "a".
The value corresponding to that value is an NSArray.
The array contains NSDictionaries with a single Key "b".
The B NSDictionaries contain another NSDictionary.
could someone show me the code to display the 3rd B NSDictionary value for "Q02" please
thanks
[[[root objectForKey:#"a"] valueForKey:#"b"] objectAtIndex:2]

Parsing JSON string to a NSMutableArray

This is my string:
[{"id":"1","nome":"Adriatik"},{"id":"2","nome":"Ard"},{"id":"3","nome":"Albana"},{"id":"4","nome":"Adriana"}]
I would like to parse all 'name' of the JSON string into a NSMutableArray.
Sorry for my english!
Whenever I have to handle some JSON code, the first thing I like to do is create a class based on the JSON text. So, for example if your JSON is representing a U.S. state, create a "State" class.
There's a cool little product that you can use for this. It's called Objectify and costs about $15. No doubt people can advise on other free stuff that might do something similar.
For the actual Json parsing, I use SBJson. There's quite a few Json parsing frameworks out there for Objective-C so definitely have a look around to see what takes your fancy.
Next, with SBJson, do the actual parsing:
-(NSDictionary *)parseJsonFromUrl
{
NSAssert(mUrl, #"Must set a url before invoking %#", __PRETTY_FUNCTION__);
// Create new SBJSON parser object
SBJsonParser *parser = [[SBJsonParser alloc] init];
// Prepare URL request to download JSON
NSURLRequest *request = [NSURLRequest requestWithURL:mUrl];
// Perform request and get JSON back as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// Get JSON as a NSString from NSData response
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
// parse the JSON response into an object
// Here we're using NSArray since we're parsing an array of JSON status objects
return [parser objectWithString:json_string error:nil];
}
That returns a NSDictionary. You know have to look through that dictionary to set the values of your model class. Here's how to do that whilst at the same time loading the values into the NSMutableArray:
-(void)downloadJsonData
{
NSDictionary *statesDict = [self parseJsonFromUrl];
NSMutableArray *statesArray = [NSMutableArray arrayWithCapacity:[statesDict count]];
for (NSDictionary *stateDict in stateDict)
{
State *aState = [[[State alloc] init] autorelease];
aState.stateId = [stateDict valueForKey:#"id"];
aState.name = [stateDict valueForKey:#"name"];
[statesArray addObject:aState];
}
}
Note that I use a property name of stateId not id so as not to clash with the Objective-C object pointer type.
Use SBJson classes and call -JSONValue method
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
// NSLog(#" Response String %#", responseString);
//converted response json string to a simple NSdictionary
NSMutableArray *results = [responseString JSONValue];