Skip to content

Commit

Permalink
Changes to prevent problems when tweet IDs go past 2^32 - 1, including:
Browse files Browse the repository at this point in the history
	Changed API entry points to use unsigned long instead of int.
	Changed request parameters to unsigned values.
	Added LARGE_ID_TEST to YAJL parser.
Added preprocessor definition for DEBUG in Debug target.
  • Loading branch information
Craig Hockenberry committed May 15, 2009
1 parent a48153e commit f32f7ae
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 55 deletions.
34 changes: 17 additions & 17 deletions MGTwitterEngine.h
Expand Up @@ -87,21 +87,21 @@

- (NSString *)getPublicTimeline; // statuses/public_timeline

- (NSString *)getFollowedTimelineSinceID:(int)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/friends_timeline
- (NSString *)getFollowedTimelineSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/friends_timeline
- (NSString *)getFollowedTimelineSinceID:(unsigned long)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/friends_timeline
- (NSString *)getFollowedTimelineSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/friends_timeline

- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(int)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/user_timeline & statuses/user_timeline/user
- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/user_timeline & statuses/user_timeline/user
- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(unsigned long)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/user_timeline & statuses/user_timeline/user
- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/user_timeline & statuses/user_timeline/user

- (NSString *)getUpdate:(int)updateID; // statuses/show
- (NSString *)getUpdate:(unsigned long)updateID; // statuses/show
- (NSString *)sendUpdate:(NSString *)status; // statuses/update
- (NSString *)sendUpdate:(NSString *)status inReplyTo:(int)updateID; // statuses/update
- (NSString *)sendUpdate:(NSString *)status inReplyTo:(unsigned long)updateID; // statuses/update

- (NSString *)getRepliesStartingAtPage:(int)pageNum; // statuses/mentions
- (NSString *)getRepliesSinceID:(int)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/mentions
- (NSString *)getRepliesSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/mentions
- (NSString *)getRepliesSinceID:(unsigned long)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/mentions
- (NSString *)getRepliesSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/mentions

- (NSString *)deleteUpdate:(int)updateID; // statuses/destroy
- (NSString *)deleteUpdate:(unsigned long)updateID; // statuses/destroy

- (NSString *)getFeaturedUsers; // statuses/features (undocumented, returns invalid JSON data)

Expand All @@ -118,14 +118,14 @@

// Direct Message methods

- (NSString *)getDirectMessagesSinceID:(int)sinceID startingAtPage:(int)pageNum; // direct_messages
- (NSString *)getDirectMessagesSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)pageNum count:(int)count; // direct_messages
- (NSString *)getDirectMessagesSinceID:(unsigned long)sinceID startingAtPage:(int)pageNum; // direct_messages
- (NSString *)getDirectMessagesSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)pageNum count:(int)count; // direct_messages

- (NSString *)getSentDirectMessagesSinceID:(int)sinceID startingAtPage:(int)pageNum; // direct_messages/sent
- (NSString *)getSentDirectMessagesSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)pageNum count:(int)count; // direct_messages/sent
- (NSString *)getSentDirectMessagesSinceID:(unsigned long)sinceID startingAtPage:(int)pageNum; // direct_messages/sent
- (NSString *)getSentDirectMessagesSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)pageNum count:(int)count; // direct_messages/sent

- (NSString *)sendDirectMessage:(NSString *)message to:(NSString *)username; // direct_messages/new
- (NSString *)deleteDirectMessage:(int)updateID;// direct_messages/destroy
- (NSString *)deleteDirectMessage:(unsigned long)updateID;// direct_messages/destroy


// Friendship methods
Expand Down Expand Up @@ -159,7 +159,7 @@

- (NSString *)getFavoriteUpdatesFor:(NSString *)username startingAtPage:(int)pageNum; // favorites

- (NSString *)markUpdate:(int)updateID asFavorite:(BOOL)flag; // favorites/create, favorites/destroy
- (NSString *)markUpdate:(unsigned long)updateID asFavorite:(BOOL)flag; // favorites/create, favorites/destroy


// Notification methods
Expand Down Expand Up @@ -194,8 +194,8 @@
// Search method

- (NSString *)getSearchResultsForQuery:(NSString *)query;
- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(int)sinceID startingAtPage:(int)pageNum count:(int)count; // search
- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(int)sinceID startingAtPage:(int)pageNum count:(int)count geocode:(NSString *)geocode;
- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(unsigned long)sinceID startingAtPage:(int)pageNum count:(int)count; // search
- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(unsigned long)sinceID startingAtPage:(int)pageNum count:(int)count geocode:(NSString *)geocode;

// Trends method

Expand Down
123 changes: 87 additions & 36 deletions MGTwitterEngine.m
Expand Up @@ -929,21 +929,26 @@ - (NSString *)getPublicTimeline
#pragma mark -


- (NSString *)getFollowedTimelineSinceID:(int)sinceID startingAtPage:(int)page count:(int)count
- (NSString *)getFollowedTimelineSinceID:(unsigned long)sinceID startingAtPage:(int)page count:(int)count
{
return [self getFollowedTimelineSinceID:sinceID withMaximumID:0 startingAtPage:page count:count];
}

- (NSString *)getFollowedTimelineSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)page count:(int)count
- (NSString *)getFollowedTimelineSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)page count:(int)count
{
#if LARGE_ID_TEST
if (sinceID > 0) sinceID -= 0x7fffffff;
if (maxID > 0) maxID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"statuses/friends_timeline.%@", API_FORMAT];

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
if (sinceID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", sinceID] forKey:@"since_id"];
[params setObject:[NSString stringWithFormat:@"%u", sinceID] forKey:@"since_id"];
}
if (maxID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", maxID] forKey:@"max_id"];
[params setObject:[NSString stringWithFormat:@"%u", maxID] forKey:@"max_id"];
}
if (page > 0) {
[params setObject:[NSString stringWithFormat:@"%d", page] forKey:@"page"];
Expand All @@ -961,22 +966,27 @@ - (NSString *)getFollowedTimelineSinceID:(int)sinceID withMaximumID:(int)maxID s
#pragma mark -


- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(int)sinceID startingAtPage:(int)page count:(int)count
- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(unsigned long)sinceID startingAtPage:(int)page count:(int)count
{
return [self getUserTimelineFor:username sinceID:sinceID withMaximumID:0 startingAtPage:0 count:count];
}

- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)page count:(int)count
- (NSString *)getUserTimelineFor:(NSString *)username sinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)page count:(int)count
{
#if LARGE_ID_TEST
if (sinceID > 0) sinceID -= 0x7fffffff;
if (maxID > 0) maxID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"statuses/user_timeline.%@", API_FORMAT];
MGTwitterRequestType requestType = MGTwitterUserTimelineRequest;

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
if (sinceID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", sinceID] forKey:@"since_id"];
[params setObject:[NSString stringWithFormat:@"%u", sinceID] forKey:@"since_id"];
}
if (maxID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", maxID] forKey:@"max_id"];
[params setObject:[NSString stringWithFormat:@"%u", maxID] forKey:@"max_id"];
}
if (page > 0) {
[params setObject:[NSString stringWithFormat:@"%d", page] forKey:@"page"];
Expand All @@ -998,9 +1008,13 @@ - (NSString *)getUserTimelineFor:(NSString *)username sinceID:(int)sinceID withM
#pragma mark -


- (NSString *)getUpdate:(int)updateID
- (NSString *)getUpdate:(unsigned long)updateID
{
NSString *path = [NSString stringWithFormat:@"statuses/show/%d.%@", updateID, API_FORMAT];
#if LARGE_ID_TEST
if (updateID > 0) updateID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"statuses/show/%u.%@", updateID, API_FORMAT];

return [self _sendRequestWithMethod:nil path:path queryParameters:nil body:nil
requestType:MGTwitterUpdateGetRequest
Expand All @@ -1014,8 +1028,12 @@ - (NSString *)sendUpdate:(NSString *)status
}


- (NSString *)sendUpdate:(NSString *)status inReplyTo:(int)updateID
- (NSString *)sendUpdate:(NSString *)status inReplyTo:(unsigned long)updateID
{
#if LARGE_ID_TEST
if (updateID > 0) updateID -= 0x7fffffff;
#endif

if (!status) {
return nil;
}
Expand All @@ -1030,7 +1048,7 @@ - (NSString *)sendUpdate:(NSString *)status inReplyTo:(int)updateID
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
[params setObject:trimmedText forKey:@"status"];
if (updateID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", updateID] forKey:@"in_reply_to_status_id"];
[params setObject:[NSString stringWithFormat:@"%u", updateID] forKey:@"in_reply_to_status_id"];
}
NSString *body = [self _queryStringWithBase:nil parameters:params prefixed:NO];

Expand All @@ -1049,21 +1067,28 @@ - (NSString *)getRepliesStartingAtPage:(int)page
return [self getRepliesSinceID:0 startingAtPage:page count:0]; // zero means default
}

- (NSString *)getRepliesSinceID:(int)sinceID startingAtPage:(int)page count:(int)count
- (NSString *)getRepliesSinceID:(unsigned long)sinceID startingAtPage:(int)page count:(int)count
{
return [self getRepliesSinceID:sinceID withMaximumID:0 startingAtPage:page count:count];
}

- (NSString *)getRepliesSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)page count:(int)count
- (NSString *)getRepliesSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)page count:(int)count
{
NSString *path = [NSString stringWithFormat:@"statuses/mentions.%@", API_FORMAT];
#if LARGE_ID_TEST
if (sinceID > 0) sinceID -= 0x7fffffff;
if (maxID > 0) maxID -= 0x7fffffff;
#endif

// NOTE: identi.ca can't handle mentions URL yet...
// NSString *path = [NSString stringWithFormat:@"statuses/mentions.%@", API_FORMAT];
NSString *path = [NSString stringWithFormat:@"statuses/replies.%@", API_FORMAT];

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
if (sinceID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", sinceID] forKey:@"since_id"];
[params setObject:[NSString stringWithFormat:@"%u", sinceID] forKey:@"since_id"];
}
if (maxID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", maxID] forKey:@"max_id"];
[params setObject:[NSString stringWithFormat:@"%u", maxID] forKey:@"max_id"];
}
if (page > 0) {
[params setObject:[NSString stringWithFormat:@"%d", page] forKey:@"page"];
Expand All @@ -1081,9 +1106,13 @@ - (NSString *)getRepliesSinceID:(int)sinceID withMaximumID:(int)maxID startingAt
#pragma mark -


- (NSString *)deleteUpdate:(int)updateID
- (NSString *)deleteUpdate:(unsigned long)updateID
{
NSString *path = [NSString stringWithFormat:@"statuses/destroy/%d.%@", updateID, API_FORMAT];
#if LARGE_ID_TEST
if (updateID > 0) updateID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"statuses/destroy/%u.%@", updateID, API_FORMAT];

return [self _sendRequestWithMethod:HTTP_POST_METHOD path:path queryParameters:nil body:nil
requestType:MGTwitterUpdateDeleteRequest
Expand Down Expand Up @@ -1180,21 +1209,26 @@ - (NSString *)getUserInformationForEmail:(NSString *)email
#pragma mark Direct Message methods


- (NSString *)getDirectMessagesSinceID:(int)sinceID startingAtPage:(int)page
- (NSString *)getDirectMessagesSinceID:(unsigned long)sinceID startingAtPage:(int)page
{
return [self getDirectMessagesSinceID:sinceID withMaximumID:0 startingAtPage:page count:0];
}

- (NSString *)getDirectMessagesSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)page count:(int)count
- (NSString *)getDirectMessagesSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)page count:(int)count
{
#if LARGE_ID_TEST
if (sinceID > 0) sinceID -= 0x7fffffff;
if (maxID > 0) maxID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"direct_messages.%@", API_FORMAT];

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
if (sinceID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", sinceID] forKey:@"since_id"];
[params setObject:[NSString stringWithFormat:@"%u", sinceID] forKey:@"since_id"];
}
if (maxID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", maxID] forKey:@"max_id"];
[params setObject:[NSString stringWithFormat:@"%u", maxID] forKey:@"max_id"];
}
if (page > 0) {
[params setObject:[NSString stringWithFormat:@"%d", page] forKey:@"page"];
Expand All @@ -1211,21 +1245,26 @@ - (NSString *)getDirectMessagesSinceID:(int)sinceID withMaximumID:(int)maxID sta

#pragma mark -

- (NSString *)getSentDirectMessagesSinceID:(int)sinceID startingAtPage:(int)page
- (NSString *)getSentDirectMessagesSinceID:(unsigned long)sinceID startingAtPage:(int)page
{
return [self getSentDirectMessagesSinceID:sinceID withMaximumID:0 startingAtPage:page count:0];
}

- (NSString *)getSentDirectMessagesSinceID:(int)sinceID withMaximumID:(int)maxID startingAtPage:(int)page count:(int)count
- (NSString *)getSentDirectMessagesSinceID:(unsigned long)sinceID withMaximumID:(unsigned long)maxID startingAtPage:(int)page count:(int)count
{
#if LARGE_ID_TEST
if (sinceID > 0) sinceID -= 0x7fffffff;
if (maxID > 0) maxID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"direct_messages/sent.%@", API_FORMAT];

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
if (sinceID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", sinceID] forKey:@"since_id"];
[params setObject:[NSString stringWithFormat:@"%u", sinceID] forKey:@"since_id"];
}
if (maxID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", maxID] forKey:@"max_id"];
[params setObject:[NSString stringWithFormat:@"%u", maxID] forKey:@"max_id"];
}
if (page > 0) {
[params setObject:[NSString stringWithFormat:@"%d", page] forKey:@"page"];
Expand Down Expand Up @@ -1268,9 +1307,13 @@ - (NSString *)sendDirectMessage:(NSString *)message to:(NSString *)username
}


- (NSString *)deleteDirectMessage:(int)updateID
- (NSString *)deleteDirectMessage:(unsigned long)updateID
{
NSString *path = [NSString stringWithFormat:@"direct_messages/destroy/%d.%@", updateID, API_FORMAT];
#if LARGE_ID_TEST
if (updateID > 0) updateID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"direct_messages/destroy/%u.%@", updateID, API_FORMAT];

return [self _sendRequestWithMethod:HTTP_POST_METHOD path:path queryParameters:nil body:nil
requestType:MGTwitterDirectMessageDeleteRequest
Expand Down Expand Up @@ -1439,17 +1482,21 @@ - (NSString *)getFavoriteUpdatesFor:(NSString *)username startingAtPage:(int)pag
#pragma mark -


- (NSString *)markUpdate:(int)updateID asFavorite:(BOOL)flag
- (NSString *)markUpdate:(unsigned long)updateID asFavorite:(BOOL)flag
{
#if LARGE_ID_TEST
if (updateID > 0) updateID -= 0x7fffffff;
#endif

NSString *path = nil;
MGTwitterRequestType requestType;
if (flag)
{
path = [NSString stringWithFormat:@"favorites/create/%d.%@", updateID, API_FORMAT];
path = [NSString stringWithFormat:@"favorites/create/%u.%@", updateID, API_FORMAT];
requestType = MGTwitterFavoritesEnableRequest;
}
else {
path = [NSString stringWithFormat:@"favorites/destroy/%d.%@", updateID, API_FORMAT];
path = [NSString stringWithFormat:@"favorites/destroy/%u.%@", updateID, API_FORMAT];
requestType = MGTwitterFavoritesDisableRequest;
}

Expand Down Expand Up @@ -1557,21 +1604,25 @@ - (NSString *)getSearchResultsForQuery:(NSString *)query
}


- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(int)sinceID startingAtPage:(int)page count:(int)count
- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(unsigned long)sinceID startingAtPage:(int)page count:(int)count
{
return [self getSearchResultsForQuery:query sinceID:sinceID startingAtPage:0 count:0 geocode:nil]; // zero means default
}

- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(int)sinceID startingAtPage:(int)page count:(int)count geocode:(NSString *)geocode
- (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(unsigned long)sinceID startingAtPage:(int)page count:(int)count geocode:(NSString *)geocode
{
#if LARGE_ID_TEST
if (sinceID > 0) sinceID -= 0x7fffffff;
#endif

NSString *path = [NSString stringWithFormat:@"search.%@", API_FORMAT];

NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
if (query) {
[params setObject:query forKey:@"q"];
}
if (sinceID > 0) {
[params setObject:[NSString stringWithFormat:@"%d", sinceID] forKey:@"since_id"];
[params setObject:[NSString stringWithFormat:@"%u", sinceID] forKey:@"since_id"];
}
if (page > 0) {
[params setObject:[NSString stringWithFormat:@"%d", page] forKey:@"page"];
Expand Down
1 change: 1 addition & 0 deletions MGTwitterEngine.xcodeproj/project.pbxproj
Expand Up @@ -421,6 +421,7 @@
/usr/include/libxml2,
"\"$(SRCROOT)/yajl/build/yajl-0.4.0/include\"",
);
OTHER_CFLAGS = "-DDEBUG";
PREBINDING = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
};
Expand Down
19 changes: 19 additions & 0 deletions MGTwitterEngineGlobalHeader.h
Expand Up @@ -50,3 +50,22 @@

#define YAJL_AVAILABLE 0

#if YAJL_AVAILABLE
/*
When enabled, this definition artificially adds 0x7ffffff to each tweet ID that is read from the API. It
also subtracts 0x7fffffff from anything it sends back to the API. This allows you to test your application
code and make sure it works well with large unsigned longs. This is important because tweet IDs that are
treated as signed integers will become negative after 2^32 - 1 (0x7fffffff). This will happen sometime
around the end of May 2009.
A future release of MGTwitterEngine will use 64-bit integers for the tweet IDs. The current change is
meant as a stopgap measure that will affect existing applications as little as possible.
*/

#define LARGE_ID_TEST 0
#else
/*
This option is only available when you are using the YAJL parser. Do not change the following definition.
*/
#define LARGE_ID_TEST 0
#endif

0 comments on commit f32f7ae

Please sign in to comment.