From fcbad97bce526345b7ea0519a5e2242e7a6fe74a Mon Sep 17 00:00:00 2001 From: Eugene Kurzberg Date: Tue, 18 Oct 2016 14:04:15 +0300 Subject: [PATCH] TSAM-8847 App auto exit after remove SD Card [Implementation] Implemented temporary copy of contact image to avoid any scenarios when image is deleted before contact is saved. Change-Id: I0a1b6a3c3306b110a9e4faadf46f065fe539a70c Signed-off-by: Eugene Kurzberg --- lib-common/inc/Common/FileUtils.h | 54 ++++++++++++++++ lib-common/src/Common/FileUtils.cpp | 72 ++++++++++++++++++++++ .../inc/Contacts/Model/ContactImageField.h | 55 +++++++++++++++++ lib-contacts/inc/Contacts/Model/ContactTextField.h | 2 +- .../src/Contacts/Model/ContactFieldFactory.cpp | 8 ++- .../src/Contacts/Model/ContactImageField.cpp | 62 +++++++++++++++++++ .../src/Contacts/Settings/ExportController.cpp | 25 ++------ 7 files changed, 257 insertions(+), 21 deletions(-) create mode 100644 lib-common/inc/Common/FileUtils.h create mode 100644 lib-common/src/Common/FileUtils.cpp create mode 100644 lib-contacts/inc/Contacts/Model/ContactImageField.h create mode 100644 lib-contacts/src/Contacts/Model/ContactImageField.cpp diff --git a/lib-common/inc/Common/FileUtils.h b/lib-common/inc/Common/FileUtils.h new file mode 100644 index 0000000..8762fab --- /dev/null +++ b/lib-common/inc/Common/FileUtils.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef COMMON_FILE_UTILS_H +#define COMMON_FILE_UTILS_H + +#include +#include + +namespace Common +{ + /** + * @brief Get available file path for a new file. + * @details Appends file index if file already exists. + * @param[in] dirPath Directory path + * @param[in] namePrefix File name prefix (before the index) + * @param[in] nameSuffix File name suffix (e.g. file extension) + * @param[in] maxCount Maximum file count (i.e. maximum index value) + * @return Available path or empty string if maximum file count is exceeded. + */ + EXPORT_API std::string getAvailableFilePath(const char *dirPath, + const char *namePrefix, const char *nameSuffix, size_t maxCount = 999); + + /** + * @brief Copy file. + * @param[in] srcPath Source path. + * @param[in] destPath Destination path. + * @return true if success. + */ + EXPORT_API bool copyFile(const char *srcPath, const char *destPath); + + /** + * @brief Remove file. + * @param[in] filePath File to remove. + * @return true if success. + */ + EXPORT_API bool removeFile(const char *filePath); +} + +#endif /* COMMON_FILE_UTILS_H */ diff --git a/lib-common/src/Common/FileUtils.cpp b/lib-common/src/Common/FileUtils.cpp new file mode 100644 index 0000000..4b568db --- /dev/null +++ b/lib-common/src/Common/FileUtils.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "Common/FileUtils.h" + +#include +#include +#include +#include +#include "Utils/Logger.h" + +std::string Common::getAvailableFilePath(const char *dirPath, + const char *namePrefix, const char *nameSuffix, size_t maxCount) +{ + for (size_t i = 0; i <= maxCount; ++i) { + char path[PATH_MAX]; + + if (i == 0) { + snprintf(path, sizeof(path), "%s/%s%s", dirPath, namePrefix, nameSuffix); + } else { + snprintf(path, sizeof(path), "%s/%s_%03zu%s", dirPath, namePrefix, i, nameSuffix); + } + + struct stat buf; + if (stat(path, &buf) != 0) { + return path; + } + } + + ERR("Maximum file count exceeded."); + return { }; +} + +bool Common::copyFile(const char *srcPath, const char *destPath) +{ + std::ifstream ifs(srcPath, std::ios::binary); + if (ifs.is_open()) { + std::ofstream ofs(destPath, std::ios::binary); + if (ofs.is_open() && !ofs.bad()) { + ofs << ifs.rdbuf(); + ofs.close(); + ifs.close(); + return true; + } + ifs.close(); + } + + return false; +} + +bool Common::removeFile(const char *filePath) +{ + struct stat st = { 0 }; + if (filePath && stat(filePath, &st) == 0) { + return std::remove(filePath) == 0; + } + return false; +} diff --git a/lib-contacts/inc/Contacts/Model/ContactImageField.h b/lib-contacts/inc/Contacts/Model/ContactImageField.h new file mode 100644 index 0000000..064ed04 --- /dev/null +++ b/lib-contacts/inc/Contacts/Model/ContactImageField.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CONTACTS_MODEL_CONTACT_IMAGE_FIELD_H +#define CONTACTS_MODEL_CONTACT_IMAGE_FIELD_H + +#include "Contacts/Model/ContactTextField.h" + +namespace Contacts +{ + namespace Model + { + /** + * @brief Represents image path field. Creates and manages temporary copy of image file. + */ + class ContactImageField : public ContactTextField + { + public: + using ContactTextField::ContactTextField; + virtual ~ContactImageField() override; + + /** + * @brief Set text field value. + */ + virtual void setValue(const char *value) override; + + protected: + /** + * @see ContactField::onUpdate() + */ + virtual void onUpdate(contacts_record_h record) override; + + private: + void removeTempFile(); + + std::string m_TempPath; + }; + } +} + +#endif /* CONTACTS_MODEL_CONTACT_IMAGE_FIELD_H */ diff --git a/lib-contacts/inc/Contacts/Model/ContactTextField.h b/lib-contacts/inc/Contacts/Model/ContactTextField.h index f7c6121..3701b58 100644 --- a/lib-contacts/inc/Contacts/Model/ContactTextField.h +++ b/lib-contacts/inc/Contacts/Model/ContactTextField.h @@ -58,7 +58,7 @@ namespace Contacts /** * @brief Set text field value. */ - void setValue(const char *value); + virtual void setValue(const char *value); protected: /** diff --git a/lib-contacts/src/Contacts/Model/ContactFieldFactory.cpp b/lib-contacts/src/Contacts/Model/ContactFieldFactory.cpp index dd93c8d..c1f072c 100644 --- a/lib-contacts/src/Contacts/Model/ContactFieldFactory.cpp +++ b/lib-contacts/src/Contacts/Model/ContactFieldFactory.cpp @@ -20,6 +20,7 @@ #include "Contacts/Model/ContactArray.h" #include "Contacts/Model/ContactBoolField.h" +#include "Contacts/Model/ContactImageField.h" #include "Contacts/Model/ContactIntField.h" #include "Contacts/Model/ContactDateField.h" #include "Contacts/Model/ContactEnumField.h" @@ -46,7 +47,12 @@ ContactFieldPtr ContactFieldFactory::createField(ContactFieldContainer *parent, case TypeEnum: field = new ContactEnumField(parent, metadata); break; case TypeText: - field = new ContactTextField(parent, metadata); break; + if (metadata.id == FieldImage) { + field = new ContactImageField(parent, metadata); + } else { + field = new ContactTextField(parent, metadata); + } + break; case TypeDate: field = new ContactDateField(parent, metadata); break; case TypeArray: diff --git a/lib-contacts/src/Contacts/Model/ContactImageField.cpp b/lib-contacts/src/Contacts/Model/ContactImageField.cpp new file mode 100644 index 0000000..937d37d --- /dev/null +++ b/lib-contacts/src/Contacts/Model/ContactImageField.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "Contacts/Model/ContactImageField.h" +#include "Common/FileUtils.h" +#include "App/Path.h" + +#include + +#define IMAGE_FILE_PREFIX "contact_image" + +using namespace Common; +using namespace Contacts::Model; + +ContactImageField::~ContactImageField() +{ + removeTempFile(); +} + +void ContactImageField::setValue(const char *value) +{ + removeTempFile(); + if (value) { + const char *ext = strrchr(value, '.'); + std::string path = getAvailableFilePath(App::getDataDir().c_str(), + IMAGE_FILE_PREFIX, ext ? ext : ""); + + if (!path.empty() && copyFile(value, path.c_str())) { + m_TempPath = std::move(path); + } + } + + ContactTextField::setValue(m_TempPath.c_str()); +} + +void ContactImageField::onUpdate(contacts_record_h record) +{ + removeTempFile(); + ContactTextField::onUpdate(record); +} + +void ContactImageField::removeTempFile() +{ + if (!m_TempPath.empty()) { + removeFile(m_TempPath.c_str()); + m_TempPath.clear(); + } +} diff --git a/lib-contacts/src/Contacts/Settings/ExportController.cpp b/lib-contacts/src/Contacts/Settings/ExportController.cpp index d295091..a8b3927 100644 --- a/lib-contacts/src/Contacts/Settings/ExportController.cpp +++ b/lib-contacts/src/Contacts/Settings/ExportController.cpp @@ -17,6 +17,7 @@ #include "Contacts/Settings/Model/Storage.h" #include "Contacts/Settings/ExportController.h" +#include "Common/FileUtils.h" #include "Ui/Popup.h" #include "Utils/Logger.h" @@ -96,28 +97,14 @@ std::string ExportController::getVcardDirectoryPath() std::string ExportController::getVcardFilePath() { std::string directoryPath = getVcardDirectoryPath(); - RETVM_IF(directoryPath.empty(), std::string(), "Cannot get directory path to storage"); + RETVM_IF(directoryPath.empty(), { }, "Cannot get directory path to storage"); - const int vcardMaxNumber = 999; - - for (int fileNumber = 1; fileNumber <= vcardMaxNumber; ++fileNumber) { - char path[BUFFER_SIZE] = { 0, }; - - if (fileNumber == 1) { - snprintf(path, sizeof(path), "%s/Contacts.vcf", directoryPath.c_str()); - } else { - snprintf(path, sizeof(path), "%s/Contacts_%03d.vcf", directoryPath.c_str(), fileNumber); - } - - struct stat buf; - if (stat(path, &buf) != 0) { - return path; - } + std::string filePath = Common::getAvailableFilePath(directoryPath.c_str(), "Contacts", ".vcf"); + if (filePath.empty()) { + notification_status_message_post(_("IDS_PB_POP_FAILED")); } - ERR("Too many vcards. Delete some before creating new."); - notification_status_message_post(_("IDS_PB_POP_FAILED")); - return std::string(); + return filePath; } void ExportController::onStart() -- 2.7.4