/* Copyright (C) 2000-2003 Max Berger This file is part of libsyncml, written for the Opengroupware project (OGo) OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id$ #import "SyncMLTagBehavior.h" #include #include "SyncMLTagSmarts.h" @implementation SyncMLTagStatusWithBehavior - (void)_saveSynched:(SyncML *)syncml cmdID:(id)_cmdid msgID:(id)_msgid { SyncMLSessionState* state = [syncml state]; SyncMLTagItem *item; NSEnumerator* enumerator; id db = [state extraInfoForCmdID:_cmdid msgID:_msgid]; enumerator = [[[state openReqCmdID:_cmdid msgID:_msgid] items] objectEnumerator]; while ((item = [enumerator nextObject])) { [syncml saveSynched:@"Version" forUID:[[item source]locuri] inDB:db to:[db versionForUID:[[item source]locuri]]]; } } - (BOOL)processCommand:(SyncML *)syncml forMsgRef:(NSString *)msgRef forMsg:(SyncMLTagSyncML *)msg inContext:(SyncMLTag *)parentTag { SyncMLSessionState* state = [syncml state]; NSString *stringdata = [data stringdata]; id sessionHandler = [syncml sessionHandler]; //NSLog(@"Status Command processed"); if ([stringdata isEqual:SYNCML_OK_S]) { if (([cmd isEqual:@"Alert"]) && ([sessionHandler server])) { // We are a server. The client should send us his modifications in // the same package, return with the new data once that is processed [syncml addSyncLaterForTarget:[sourcerefs objectAtIndex:0] source:[targetrefs objectAtIndex:0]]; } else if ([cmd isEqual:@"Add"]) { [self _saveSynched:syncml cmdID:[self cmdref] msgID:[self msgref]]; } [state closeReqCmdID:[self cmdref] msgID:[self msgref]]; } else if ([stringdata isEqual:SYNCML_AUTHENTICATION_ACCEPTED_S]) { [state setIAmAuthenticated:YES]; } else if ([stringdata isEqual:SYNCML_MISSING_CREDENTIALS_S] && [cmd isEqual:@"SyncHdr"]) { [state setSendInitialAlerts:YES]; [state setIAmAuthenticated:NO]; if ([[[chal meta]type]caseInsensitiveCompare:SYCNML_AUTH_BASIC]== NSOrderedSame) { [state setAuthenticationType:SYCNML_AUTH_BASIC]; if ([[[chal meta]format]caseInsensitiveCompare:SYNCML_FORMAT_BASE64]== NSOrderedSame) { NSString *s; [state setAuthenticationFormat:SYNCML_FORMAT_BASE64]; s = [NSString stringWithFormat:@"%@:%@", [sessionHandler provideUsername], [sessionHandler providePlainPassword]]; s = [s stringByEncodingBase64]; [state setAuthenticationData:s]; } else { //FIXME!!! } } else if ([[[chal meta]type]caseInsensitiveCompare:SYCNML_AUTH_MD5]== NSOrderedSame) { // FIXME } else { // FIXME } } else if ([stringdata isEqual:SYNCML_FORBIDDEN_S] && [cmd isEqual:@"SyncHdr"]) { [sessionHandler invalidCredentials]; [state setSendInitialAlerts:NO]; } return YES; } @end /* SyncMLTagStatusWithBehavior */ @implementation SyncMLTagAlertWithBehavior - (BOOL)processCommand:(SyncML*)syncml forMsgRef:(NSString *)msgRef forMsg:(SyncMLTagSyncML*)msg inContext:(SyncMLTag*)parentTag { SyncMLTagStatus *status = nil; SyncMLTagItem *item; SyncMLTagItem *returnItem; SyncMLTagData *returnData; SyncMLTagAnchor *anchor; NSEnumerator *enumerator; id db; int alert; enumerator = [items objectEnumerator]; while ((item = [enumerator nextObject])) { db = [syncml databaseHandlerForURI:[[item target]locuri]]; if (db) { if (!([[syncml state] otherIsAuthenticated])&& ([[syncml sessionHandler] requireAuthentication])) { if (!noresp) { status = [syncml addStatus:SYNCML_FORBIDDEN msgRef:msgRef cmdRef:cmdid cmd:@"Alert" toMsg:msg]; } // FIXME: Add something else? } else { BOOL fallback; alert = [[data stringdata]intValue]; [[syncml state]setSync:alert forDB:[db databaseLocation]]; if (!noresp) { status = [syncml addStatus:SYNCML_OK msgRef:msgRef cmdRef:cmdid cmd:@"Alert" toMsg:msg]; } [status setTargetref:[[item source]locuri]]; [status setSourceref:[[item target]locuri]]; fallback = [syncml compareAnchors:[[item meta]anchor] forDB:db]; // FIXME: use fallback returnItem = [[SyncMLTagItemWithSmartEncode alloc]init]; returnData = [[SyncMLTagData alloc]init]; anchor = [[SyncMLTagAnchor alloc]init]; [anchor setNext:[[[item meta]anchor]next]]; //[anchor setLast:[db lastAnchorWith:[[item source]locuri]]]; [returnData setAnchor:anchor]; [anchor release]; [returnItem setData:returnData]; [returnData release]; [status setItem:returnItem]; [returnItem release]; // FIXME: Check for invalid Sync Types if ([[syncml sessionHandler]server]) { // Server: May overwrite SyncType //FIXME: Check for Fallback Necessary /* if ((alert==SYNCML_SYNC_ALERT_TWO_WAY) || (alert==SYNCML_SYNC_ALERT_ONE_WAY_FROM_CLIENT) || (alert==SYNCML_SYNC_ALERT_ONE_WAY_FROM_SERVER)) fallback = [SyncML compareAnchors:anchor withDB:db]; */ // FIXME: If fallback necessary, send error. // The server always answers an alert with an alert, since the // client might have found out that the sync anchors are out of // sync. //if ([[syncml state]sendInitialAlerts]) { [syncml addAlert:alert to:msg withDatabase:db forTarget:[[item source]locuri]]; [[syncml state]setSendInitialAlerts:NO]; //} } else { // We are a client. we have just received the go to send our // modifications to the server // FIXME: Check if fallback, and if so, send alert again. [syncml addSyncTarget:[[item source]locuri] source:[[item target]locuri] toMsg:msg]; } } } else { // FIXME: DB not found } } return YES; } @end /* SyncMLTagAlertWithBehavior */ @implementation SyncMLTagSyncWithBehavior - (BOOL) processCommand:(SyncML*)syncml forMsgRef:(NSString *)msgRef forMsg:(SyncMLTagSyncML*)msg inContext:(SyncMLTag*)parentTag { id db; int alert; SyncMLTagStatus *status; db = [syncml databaseHandlerForURI:[target locuri]]; alert = [[syncml state]syncForDB:[db databaseLocation]]; if ([[syncml sessionHandler]server]) { if (alert==SYNCML_SYNC_ALERT_REFRESH_FROM_CLIENT) { [db deleteAll]; [syncml forgetSynchedWithDB:db]; } } else { if ((alert==SYNCML_SYNC_ALERT_REFRESH_FROM_SERVER)|| (alert==SYNCML_SYNC_ALERT_SLOW_SYNC)) { [db deleteAll]; [syncml forgetSynchedWithDB:db]; } } [syncml processCommandsFrom:self forMsgRef:msgRef forMsg:msg]; if (!noresp) { status = [syncml addStatus:SYNCML_OK msgRef:msgRef cmdRef:cmdid cmd:@"Sync" toMsg:msg]; } [[[syncml state] mappingDBs]addObject:[db databaseLocation]]; return YES; } @end /* SyncMLTagSyncWithBehavior */ @implementation SyncMLTagAddWithBehavior - (BOOL) processCommand:(SyncML*)syncml forMsgRef:(NSString *)msgRef forMsg:(SyncMLTagSyncML*)msg inContext:(SyncMLTag*)parentTag { SyncMLTagItem *item; NSEnumerator* enumerator; id context = parentTag; id db; SyncMLTagStatus *status; NSString *newUID; if ([context respondsToSelector:@selector(target)]) { db = [syncml databaseHandlerForURI:[[context target]locuri]]; } if (db) { enumerator = [items objectEnumerator]; while ((item = [enumerator nextObject])) { newUID = [db addElement:[[item data]stringdata] withUri:[[item source]locuri]]; [syncml saveSynched:@"Version" forUID:newUID inDB:db to:[db versionForUID:newUID]]; if (![[syncml sessionHandler]server]) { [syncml addMapToMsg:msg target:[[item source]locuri] source:newUID targetDB:[[(SyncMLTagSync*)parentTag source]locuri] sourceDB:[db databaseLocation]]; } } } else { // FIXME: return bad status return NO; } if (!noresp) { status = [syncml addStatus:SYNCML_OK msgRef:msgRef cmdRef:cmdid cmd:@"Add" toMsg:msg]; } return YES; } @end /* SyncMLTagAddWithBehavior */ @implementation SyncMLTagMapWithBehavior - (BOOL) processCommand:(SyncML*)syncml forMsgRef:(NSString *)msgRef forMsg:(SyncMLTagSyncML*)msg inContext:(SyncMLTag*)parentTag { id db; NSEnumerator *enumerator; SyncMLTagMapItem *item; SyncMLTagStatus *status = nil; db = [syncml databaseHandlerForURI:[[self target]locuri]]; if (db) { enumerator = [[self mapitems]objectEnumerator]; while ((item = [enumerator nextObject])) { #if 0 NSLog(@"Map %@ %@ %@",[db databaseLocation],[[item target] locuri], [[item source] locuri]); #endif [syncml saveSynched:@"Map" forUID:[[item target]locuri] inDB:db to:[[item source]locuri]]; } } else { // FIXME: db not found } status = [syncml addStatus:SYNCML_OK msgRef:msgRef cmdRef:cmdid cmd:@"Map" toMsg:msg]; return YES; } @end /* SyncMLTagMapWithBehavior */