3

I am developing an app using data from google reader's API and using GData for login.

I want to be able to mark a post inside a table cell as read / unread, but am finding the fact that this is all mainly undocumented hard to work out a solution, any ideas / links?

Here is the code for the mark read button:

//Get the token

NSString *tokenString = [NSString stringWithFormat:@"https://www.google.com/reader/api/0/token"];

NSURL *tokenURL = [NSURL URLWithString:tokenString];
NSMutableURLRequest *tokenRequest = [NSMutableURLRequest requestWithURL:tokenURL];

NSString *tokenStringResult;
NSArray *listItems;

NSError *tokenError = nil;
NSURLResponse *tokenResponse = nil;
NSData *tokenData = [NSURLConnection sendSynchronousRequest:tokenRequest
                                          returningResponse:&tokenResponse
                                                      error:&tokenError];
if (tokenData) 
{
    tokenStringResult = [[NSString alloc] initWithData:tokenData encoding:NSUTF8StringEncoding];

    listItems = [tokenStringResult componentsSeparatedByString:@"/"];
} 
else 
{
    NSLog(@"tokenError = %@", tokenError);
}

// Mark it as read

NSString *readerURLString = [NSString stringWithFormat:@"http://www.google.com/reader/api/0/edit-tag?a=user/-/state/com.google/read&async=true&s=feed/%@&i=%@&T=%@", siteLink, postID, [listItems lastObject]];

NSURL *readerURL = [NSURL URLWithString:readerURLString];

NSMutableURLRequest *readerRequest = [NSMutableURLRequest requestWithURL:readerURL];

[mAuth authorizeRequest:readerRequest];

NSError *error = nil;
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:readerRequest
                                     returningResponse:&response
                                                 error:&error];
if (data) 
{
    NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *) response;
    assert( [httpResponse isKindOfClass:[NSHTTPURLResponse class]] );

    NSLog(@"response.allHeaderFields = %@", [httpResponse allHeaderFields]);

    NSLog(@"response.statusCode = %i", [httpResponse statusCode]);

} 

the log from this is:

response.statusCode = {
"Cache-Control" = "private, max-age=0";
"Content-Length" = 1334;
"Content-Type" = "text/html; charset=UTF-8";
Date = "Fri, 21 Jan 2011 03:49:07 GMT";
Expires = "Fri, 21 Jan 2011 03:49:07 GMT";
Server = GSE;
"X-Content-Type-Options" = nosniff;
"X-Frame-Options" = SAMEORIGIN;
"X-Reader-Google-Version" = "527-000";
"X-Reader-User" = 01940378872835844713;
"X-Xss-Protection" = "1; mode=block";
}
response.statusCode = 400
daihovey
  • 3,485
  • 13
  • 66
  • 110

2 Answers2

1

So through alot of trial and error I've got it working.

EDIT - Added Auth code

NSString *GOOGLE_CLIENT_AUTH_URL    = @"https://www.google.com/accounts/ClientLogin?client=SomeName";
NSString *gSourceString             = @"SomeName";

NSMutableURLRequest *httpReq = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:GOOGLE_CLIENT_AUTH_URL]];
[httpReq setTimeoutInterval:30.0];
[httpReq setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[httpReq setHTTPMethod:@"POST"];

[httpReq addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSString *requestBody = [[NSString alloc]  initWithFormat:@"Email=%@&Passwd=%@&service=reader&accountType=HOSTED_OR_GOOGLE&source=%@", userString, passwordString, [NSString stringWithFormat:@"%@%d", gSourceString]];

[httpReq setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding]];

[requestBody release];

NSHTTPURLResponse *response = nil;

NSData *data    = nil;
NSString *responseStr       = nil;
NSArray *responseLines      = nil;

int responseStatus = 0;

data = [NSURLConnection sendSynchronousRequest:httpReq returningResponse:&response error:&error];

[httpReq release];

if ([data length] > 0) 
{
    responseStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    responseStatus = [response statusCode];

    if (responseStatus == 200 ) 
    {
        authOK = TRUE;
        NSLog(@"Successfully authenticated with Google.");
        NSArray *authLines = nil;
        authLines  = [responseStr componentsSeparatedByString:@"\n"];

        int j;
        for (j =0; j < [authLines count]; j++ ) 
        {
            if ([[authLines objectAtIndex:j] rangeOfString:@"Auth="].length != 0) {

                NSMutableString *teststring = [NSMutableString stringWithString:[authLines objectAtIndex:j]];

                [teststring replaceCharactersInRange:NSMakeRange(0,4) withString:@"auth"];

                authString = teststring;
            }
        }
    }
    }


 NSString *auth = [[NSString alloc] initWithString: [NSString stringWithFormat:@"GoogleLogin %@", authString]];

NSDictionary *createHeader = [[NSDictionary dictionaryWithObjectsAndKeys:@"www.google.com", @"Host", @"EditApp", @"User-Agent", @"gzip, deflate", @"Accept-Encoding", auth, @"Authorization", nil]retain];

[auth release];

NSURL *url =[NSURL URLWithString:@"http://www.google.com/reader/api/0/token?client=EditApp"];
NSData *recieveData;
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc]initWithURL:url];
[urlRequest setHTTPMethod:@"GET"];
[urlRequest setAllHTTPHeaderFields:createHeader];
NSURLResponse *response;
NSError *error;
recieveData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];

// Get token 

NSString *pretokenString = [[NSString alloc] initWithData:recieveData encoding:NSASCIIStringEncoding];

tokenString = [pretokenString substringWithRange:NSMakeRange(2, [pretokenString length]-2)];

[pretokenString release];

[urlRequest release];

NSMutableURLRequest *thttpReq = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com/reader/api/0/edit-tag?"]];

[thttpReq setTimeoutInterval:30.0];

[thttpReq setHTTPMethod:@"POST"];

NSString *authHeader = [NSString stringWithFormat:@"GoogleLogin %@", authString];
[thttpReq addValue:authHeader forHTTPHeaderField:@"Authorization"];

[thttpReq addValue:@"Content-Type" forHTTPHeaderField:@"application/x-www-form-urlencoded"];

// siteLink is the url of the feed
// googlePostID is the id from the XML output: tag:google.com,2005:reader/item/e3345c69e174bdec

NSString *trequestBody = [[NSString alloc] initWithFormat:@"a=user/-/state/com.google/read&ac=edit-tags&s=feed/%@&i=%@&T=%@", siteLink, googlePostID, tokenString];

[thttpReq setHTTPBody:[trequestBody dataUsingEncoding:NSASCIIStringEncoding]];

NSURLConnection *con = [[NSURLConnection alloc]
                            initWithRequest:thttpReq
                            delegate:self
                            startImmediately:NO];
[con scheduleInRunLoop:[NSRunLoop currentRunLoop]
                   forMode:NSRunLoopCommonModes];
[con start];
daihovey
  • 3,485
  • 13
  • 66
  • 110
0

If you are familiar with php I wrote a tutorial on using the google readi api recently. http://mobile.tutsplus.com/tutorials/mobile-web-apps/building-a-mobile-web-application-with-the-google-reader-api/

One thing I notice is that in this string

http://www.google.com/reader/api/0/edit-tag/a=user/-/state/com.google/read&async=true&s=feed/%@&i=%@

Your not including the "edit" token the url should look like this. and you need the ? after edit-tag.

http://www.google.com/reader/api/0/edit-tag?a=user/-/state/com.google/read&async=true&s=feed/%@&i=%@&T=%@

You can get the "edit" token from this link once you have the user logged in, https://www.google.com/reader/api/0/token

Sorry can't help with objective-c stuff.

smilbandit
  • 524
  • 3
  • 6
  • thanks but I think I need to either add headers or post data using the GData login – daihovey Jan 21 '11 at 01:33
  • You'll defiantly need the gdata login as part of the headers for all interactions with google reader. there's an additional token that's necessary for any interactions that either add, remove or update data. – smilbandit Jan 21 '11 at 03:13
  • Yes but [mAuth authorizeRequest:readerRequest]; should add the OAoth tokens to the header but it doesnt seem to be. – daihovey Jan 21 '11 at 03:53
  • Are you getting back a token? I'm not familiar with objective-c but the token request url needs the auth headers also. my guess is that if [mAuth authorizeRequest:readerRequest]; does it for the readerRequest you'll also need a [mAuth authorizeRequest:tokenRequest]; for tokenRequest. Also the token can be retrieved and stored in a global variable at the same time as you do the oauth process, there's no need to get the token at each request. – smilbandit Jan 21 '11 at 14:45