TSAM-8847 App auto exit after remove SD Card 07/92707/4
authorEugene Kurzberg <i.kurtsberg@samsung.com>
Tue, 18 Oct 2016 11:04:15 +0000 (14:04 +0300)
committerEugene Kurzberg <i.kurtsberg@samsung.com>
Tue, 18 Oct 2016 11:04:15 +0000 (14:04 +0300)
[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 <i.kurtsberg@samsung.com>
lib-common/inc/Common/FileUtils.h [new file with mode: 0644]
lib-common/src/Common/FileUtils.cpp [new file with mode: 0644]
lib-contacts/inc/Contacts/Model/ContactImageField.h [new file with mode: 0644]
lib-contacts/inc/Contacts/Model/ContactTextField.h
lib-contacts/src/Contacts/Model/ContactFieldFactory.cpp
lib-contacts/src/Contacts/Model/ContactImageField.cpp [new file with mode: 0644]
lib-contacts/src/Contacts/Settings/ExportController.cpp

diff --git a/lib-common/inc/Common/FileUtils.h b/lib-common/inc/Common/FileUtils.h
new file mode 100644 (file)
index 0000000..8762fab
--- /dev/null
@@ -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 <tizen.h>
+#include <string>
+
+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 (file)
index 0000000..4b568db
--- /dev/null
@@ -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 <fstream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/limits.h>
+#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 (file)
index 0000000..064ed04
--- /dev/null
@@ -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 */
index f7c6121..3701b58 100644 (file)
@@ -58,7 +58,7 @@ namespace Contacts
                        /**
                         * @brief Set text field value.
                         */
-                       void setValue(const char *value);
+                       virtual void setValue(const char *value);
 
                protected:
                        /**
index dd93c8d..c1f072c 100644 (file)
@@ -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 (file)
index 0000000..937d37d
--- /dev/null
@@ -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 <string.h>
+
+#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();
+       }
+}
index d295091..a8b3927 100644 (file)
@@ -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()