2 * Funambol is a mobile platform developed by Funambol, Inc.
3 * Copyright (C) 2003 - 2007 Funambol, Inc.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Affero General Public License version 3 as published by
7 * the Free Software Foundation with the addition of the following permission
8 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
9 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
10 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program; if not, see http://www.gnu.org/licenses or write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
23 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU Affero General Public License version 3.
29 * In accordance with Section 7(b) of the GNU Affero General Public License
30 * version 3, these Appropriate Legal Notices must retain the display of the
31 * "Powered by Funambol" logo. If the display of the logo is not reasonably
32 * feasible for technical reasons, the Appropriate Legal Notices must display
33 * the words "Powered by Funambol".
35 #include "spds/SyncItem.h"
36 #include "spds/SyncItemStatus.h"
37 #include "base/util/utils.h"
39 #include "syncml/core/TagNames.h"
40 #include "base/util/ArrayListEnumeration.h"
41 #include "client/BriefcaseCacheSyncSource.h"
44 #define ERR_FILE_SYSTEM 1
45 #define ERR_NO_FILES_TO_SYNC 2
46 #define ERR_BAD_FILE_CONTENT 3
49 static StringBuffer getCompleteName(StringBuffer& dir, const WCHAR *name) {
51 char* t = toMultibyte(name);
52 StringBuffer pathName(dir);
60 BriefcaseCacheSyncSource::BriefcaseCacheSyncSource(
62 AbstractSyncSourceConfig* sc)
63 : CacheSyncSource(name, sc), dir(DEFAULT_BRIEFCASE_DIR) {
67 BriefcaseSyncSource::BriefcaseSyncSource(const BriefcaseSyncSource& s):
68 syncMode(s.getSyncMode()),
69 lastSync(s.getLastSync()),
70 nextSync(s.getNextSync()),
71 lastAnchor(s.getLastAnchor()),
72 nextAnchor(s.getNextAnchor()),
73 filter(s.getFilter()),
81 BriefcaseSyncSource::BriefcaseSyncSource(const BriefcaseSyncSource& s) : TrackingSyncSource(s) {
83 setSyncMode(s.getSyncMode());
84 setLastSync(s.getLastSync());
85 setNextSync(s.getNextSync());
86 setLastAnchor(s.getLastAnchor());
87 setNextAnchor(s.getNextAnchor());
88 setFilter(s.getFilter());
90 setReport(s.getReport());
96 BriefcaseCacheSyncSource::~BriefcaseCacheSyncSource() {}
99 int BriefcaseCacheSyncSource::removeAllItems() {
100 removeFileInDir(dir);
105 int BriefcaseCacheSyncSource::parseFileData(FileData& file, SyncItem& item) {
107 if (file.parse(item.getData(),item.getDataSize())) {
108 LOG.info("Error parsing item from server. Using its content directly");
115 int BriefcaseCacheSyncSource::saveFileData(FileData& file) {
117 StringBuffer completeName(getCompleteName(dir, file.getName()));
119 int ret = STC_COMMAND_FAILED;
120 if (!saveFile(completeName, file.getBody(), file.getSize(), true)) {
121 LOG.info("Error saving file");
122 return STC_COMMAND_FAILED;
128 int BriefcaseCacheSyncSource::saveFileData(SyncItem& item, bool isUpdate) {
130 StringBuffer completeName(getCompleteName(dir, item.getKey()));
131 if (!isUpdate) { // it is an add
132 FILE *fh = fopen(completeName, "r");
135 return STC_ALREADY_EXISTS;
138 if (!saveFile(completeName, (const char *)item.getData(), item.getDataSize(), true)) {
139 setErrorF(ERR_FILE_SYSTEM, "Error saving file %s", completeName.c_str());
140 LOG.error("%s", getLastErrorMsg());
141 report->setLastErrorCode(ERR_FILE_SYSTEM);
142 report->setLastErrorMsg(getLastErrorMsg());
143 report->setState(SOURCE_ERROR);
144 return STC_COMMAND_FAILED;
148 return STC_ITEM_ADDED;
155 Enumeration* BriefcaseCacheSyncSource::getAllItemList() {
158 // Get the list of the files that are in the directory
160 ArrayList currentKeys;
161 Enumeration* allKeys = NULL;
163 char** fileNames = readDir((char*)dir.c_str(), &count);
164 LOG.info("The client number of files to sync are %i", count);
166 for (int i = 0; i < count; i++) {
168 StringBuffer s(fileNames[i]);
174 for (int i = 0; i < count; i++) {
175 delete [] fileNames[i]; fileNames[i] = NULL;
177 if (fileNames != NULL) {
178 delete [] fileNames; fileNames = NULL;
181 if (currentKeys.size() > 0) {
182 allKeys = new ArrayListEnumeration(currentKeys);
189 * Adds an item on the file system in the set directory.
192 int BriefcaseCacheSyncSource::insertItem(SyncItem& item) {
194 int ret = STC_COMMAND_FAILED;
197 if (parseFileData(file, item) == 0) {
198 if (file.getSize() >= 0) {
199 ret = saveFileData(file);
200 if (ret = STC_COMMAND_FAILED) {
203 item.setKey(file.getName());
204 ret = STC_ITEM_ADDED;
205 LOG.debug("Added item: %" WCHAR_PRINTF, file.getName());
209 ret = saveFileData(item, false);
215 int BriefcaseCacheSyncSource::removeItem(SyncItem& item) {
217 const char* filename = toMultibyte(item.getKey());
218 removeFileInDir(dir, filename);
219 if (filename) { delete [] filename; filename = NULL; }
220 LOG.debug("Added deleted: %" WCHAR_PRINTF, item.getKey());
225 int BriefcaseCacheSyncSource::modifyItem(SyncItem& item) {
227 int ret = STC_COMMAND_FAILED;
230 if (parseFileData(file, item) == 0) {
231 if (file.getSize() >= 0) {
232 ret = saveFileData(file);
233 if (ret = STC_COMMAND_FAILED) {
235 } else { // don't add the item if it doesn't exist
240 ret = saveFileData(item, true);
247 * Get the content of an item given the key. It is used to populate
248 * the SyncItem before the engine uses it in the usual flow of the sync.
249 * It is used also by the itemHandler if needed
250 * (i.e. in the cache implementation)
252 * @param key the local key of the item
253 * @param size OUT: the size of the content
255 void* BriefcaseCacheSyncSource::getItemContent(StringBuffer& key, size_t* size) {
257 char* content = NULL;
259 WCHAR* t = toWideChar(key);
260 StringBuffer completeName(getCompleteName(dir, t));
261 if (readFile(completeName, &content, size, true)) {
262 LOG.debug("Content succesfully read");
264 LOG.error("Content of the file not read");
272 ArrayElement* BriefcaseCacheSyncSource::clone() {
274 BriefcaseSyncSource* s = new BriefcaseSyncSource(*this);
277 BriefcaseCacheSyncSource* s = new BriefcaseCacheSyncSource(getName(), &(getConfig()));
282 void BriefcaseCacheSyncSource::assign(BriefcaseCacheSyncSource& s) {
284 setSyncMode(s.getSyncMode());
285 setLastSync(s.getLastSync());
286 setNextSync(s.getNextSync());
287 setLastAnchor(s.getLastAnchor());
288 setNextAnchor(s.getNextAnchor());
289 setFilter(s.getFilter());
291 setReport(s.getReport());