📄 syncmlprocessor.cpp
字号:
/*
* Copyright (C) 2003-2007 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
#include <stdlib.h>
#include "base/Log.h" // TBR
#include "base/util/ArrayList.h"
#include "base/util/utils.h"
#include "spds/constants.h"
#include "spds/SyncMLProcessor.h"
#include "spds/spdsutils.h"
#include "event/FireEvent.h"
/*
* This class is responsible for the processing of the incoming messages.
*/
/*
* Constructor
*/
SyncMLProcessor::SyncMLProcessor() : XMLProcessor() {
}
SyncML* SyncMLProcessor::processMsg(char* msg) {
SyncML* syncml = Parser::getSyncML(msg);
return syncml;
}
int SyncMLProcessor::processSyncHdrStatus(SyncML* syncml) {
int ret = getStatusCode(syncml->getSyncBody(), NULL, SYNC_HDR);
// Fire Sync Status Event: syncHdr status from server
fireSyncStatusEvent(SYNC_HDR, ret, NULL, NULL, NULL , SERVER_STATUS);
return ret;
}
int SyncMLProcessor::processAlertStatus(SyncSource& source, SyncML* syncml, ArrayList* alerts) {
int ret = -1;
const char* name = NULL;
Status* s = NULL;
Data* data = NULL;
SourceRef* sourceRef = NULL;
if (alerts->size()) {
ArrayList* list = syncml->getSyncBody()->getCommands();
for (int i = 0; i < list->size(); i++) {
// is returned the pointer to the element not a new element
name = ((AbstractCommand*)(list->get(i)))->getName();
if (name && strcmp(name, STATUS) == 0) {
s = (Status*)list->get(i);
if (strcmp(s->getCmd(), ALERT) == 0) {
sourceRef = (SourceRef*)(s->getSourceRef()->get(0));
if (sourceRef) {
if (strcmp(_wcc(source.getName()),
sourceRef->getValue()) == 0) {
ret = getAlertStatusCode(s, _wcc(source.getName()));
break;
}
} else {
// Server did not include <SourceRef>, which
// is a violation of the standard for commands
// which were sent with <SourceRef>. Happens
// with Synthesis server if authentication
// failed, in which case we can simply ignore
// it.
}
}
}
}
}
// Fire a syncStatus event: Alert status from server
fireSyncStatusEvent(ALERT, ret, source.getConfig().getName(), source.getConfig().getURI(), NULL, SERVER_STATUS);
return ret;
}
/*
* Processes the initialization response. Returns 0 in case of success, an
* error code in case of error.
*
* @param msg the response from the server
*/
int SyncMLProcessor::processServerAlert(SyncSource& source, SyncML* syncml) {
int ret = -1;
int iterator = 0;
AbstractCommand* a = NULL;
Item* item = NULL;
BOOL found = FALSE;
ret = 0;
do {
a = getCommand(syncml->getSyncBody(), ALERT, iterator);
if (a == NULL) {
// This happens with the Synthesis server's reply:
// instead of sending SyncBody/Alert we get SyncBody/Put
// with device infos and a SyncBody/Get requesting our own
// device infos. Ignoring the request is not correct, but
// allows synchronization to proceed and complete eventually
// without any further errors. For that to work we must not
// set lastErrorCode here, as it will be checked at the end of
// the sync.
//
// lastErrorCode = ERR_REPRESENTATION;
// sprintf(lastErrorMsg, "SyncBody/Alert not found!");
goto finally;
}
Alert* alert = (Alert*)a;
Item* item = NULL;
ArrayList* itemList = alert->getItems();
for (int i = 0; i < itemList->size(); i++) {
item = (Item*)getArrayElement(itemList, i);
const char *locURI = ((Target*)item->getTarget())->getLocURI();
if (strcmp( locURI, _wcc(source.getName()) ) == 0) {
if (alert->getData() == NULL) {
lastErrorCode = ERR_REPRESENTATION;
sprintf(lastErrorMsg, "SyncBody/Alert/Data not found!");
goto finally;
}
source.setSyncMode((SyncMode)alert->getData());
ret = 0;
found = TRUE;
break;
}
}
iterator++;
if (found)
break;
} while(a);
finally:
return ret;
}
char** SyncMLProcessor::getSortedSourcesFromServer(SyncML* syncml, int sourcesNumber) {
char** sourceList = new char*[sourcesNumber+1];
int iterator = 0;
AbstractCommand* a = NULL;
Item* item = NULL;
do {
a = getCommand(syncml->getSyncBody(), ALERT, iterator);
if (a == NULL) {
goto finally;
}
Alert* alert = (Alert*)a;
Item* item = NULL;
ArrayList* itemList = alert->getItems();
for (int i = 0; i < itemList->size(); i++) {
item = (Item*)getArrayElement(itemList, i);
const char *locURI = ((Target*)item->getTarget())->getLocURI();
sourceList[iterator] = stringdup(locURI);
}
iterator++;
} while(a);
finally:
sourceList[iterator] = NULL;
return sourceList;
}
int SyncMLProcessor::processItemStatus(SyncSource& source, SyncBody* syncBody) {
ArrayList* items = NULL;
Item* item = NULL;
SourceRef* sourceRef = NULL;
Status* s = NULL;
const char* name = NULL;
Data* data = NULL;
int ret = 0;
ArrayList* list = getCommands(syncBody, STATUS);
for (int i = 0; i < list->size(); i++) {
s = (Status*)list->get(i);
name = s->getCmd();
data = s->getData();
if (strcmp(name, SYNC) == 0){
char *srcname = toMultibyte(source.getName());
int alertStatus = getAlertStatusCode(s, srcname);
delete [] srcname;
/*
* Try to find if the server send a message together the error code if any
* The items in the status message should be always one...
*/
char *statusMessage = NULL;
items = s->getItems();
for (int k = 0; k < items->size(); k++) {
item = (Item*)items->get(k);
if (item) {
ComplexData* cd = item->getData();
if (cd) {
statusMessage = stringdup(cd->getData());
}
}
}
// Fire Sync Status Event: sync status from server
fireSyncStatusEvent(SYNC, s->getStatusCode(), source.getConfig().getName(), source.getConfig().getURI(), NULL, SERVER_STATUS);
if(alertStatus < 0 || alertStatus >=300){
if (statusMessage) {
strcpy(lastErrorMsg, statusMessage);
} else {
strcpy(lastErrorMsg, "Error in sync status sent by server.");
}
if ((ret = alertStatus) < 0)
LOG.error("processItemStatus: status not found in SYNC");
else
LOG.error("processItemStatus: server sent status %d in SYNC", alertStatus);
break;
}
if (statusMessage) {
delete [] statusMessage;
}
}
else if (strcmp(name, ADD) == 0 ||
strcmp(name, REPLACE) == 0 ||
strcmp(name, DEL) == 0) {
int k;
items = s->getItems();
long val = strtol(data->getData() , NULL, 10);
for (k = 0; k < items->size(); k++) {
item = (Item*)items->get(k);
if (item) {
Source* itemSource = item->getSource();
if (itemSource) {
WCHAR *uri = toWideChar(itemSource->getLocURI());
ComplexData* cd = item->getData();
WCHAR *statusMessage = NULL;
if (cd) {
statusMessage = toWideChar(cd->getData());
}
// Fire Sync Status Event: item status from server
fireSyncStatusEvent(s->getCmd(), s->getStatusCode(), source.getConfig().getName(), source.getConfig().getURI(), uri, SERVER_STATUS);
// Update SyncReport
source.getReport()->addItem(SERVER, s->getCmd(), uri, s->getStatusCode(), statusMessage);
source.setItemStatus(uri, val);
delete [] uri;
if (statusMessage)
delete [] statusMessage;
} else {
// the item might consist of additional information, as in:
// <SourceRef>pas-id-44B544A600000092</SourceRef>
// <Data>200</Data>
// <Item><Data>Conflict resolved by server</Data></Item>
}
}
}
items = s->getSourceRef();
for (k = 0; k < items->size(); k++) {
sourceRef = (SourceRef*)items->get(k);
if (sourceRef) {
WCHAR *srcref = toWideChar(sourceRef->getValue());
// Fire Sync Status Event: item status from server
fireSyncStatusEvent(s->getCmd(), s->getStatusCode(), source.getConfig().getName(), source.getConfig().getURI(), srcref, SERVER_STATUS);
// Update SyncReport
source.getReport()->addItem(SERVER, s->getCmd(), srcref, s->getStatusCode(), NULL);
source.setItemStatus(srcref, val);
delete [] srcref;
}
}
}
}
deleteArrayList(&list);
return ret;
}
/*
* Processes the initialization response. Returns 0 in case of success, an
* error code in case of error.
*
* @param msg the response from the server
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -